function getElementsInRectangle()

in packages/ketcher-react/src/script/editor/tool/helper/locate.ts [27:234]


function getElementsInRectangle(restruct: ReStruct, p0, p1) {
  const bondList: Array<number> = [];
  const atomList: Array<number> = [];
  const sGroups = restruct.sgroups;
  const functionalGroups = restruct.molecule.functionalGroups;
  const struct: Struct = restruct.molecule;

  const x0 = Math.min(p0.x, p1.x);
  const x1 = Math.max(p0.x, p1.x);
  const y0 = Math.min(p0.y, p1.y);
  const y1 = Math.max(p0.y, p1.y);

  const topLeftPosition = new Vec2(x0, y0);
  const topRightPosition = new Vec2(x1, y0);
  const bottomRightPosition = new Vec2(x1, y1);
  const bottomLeftPosition = new Vec2(x0, y1);

  const polygon = [
    topLeftPosition,
    topRightPosition,
    bottomRightPosition,
    bottomLeftPosition,
  ];

  restruct.bonds.forEach((bond, bid) => {
    if (
      FunctionalGroup.isBondInContractedFunctionalGroup(
        bond.b,
        sGroups,
        functionalGroups,
      )
    ) {
      return;
    }

    let center: Vec2;
    if (bond.b.isExternalBondBetweenMonomers(struct)) {
      const firstMonomer = struct.getGroupFromAtomId(bond.b.begin);
      const secondMonomer = struct.getGroupFromAtomId(bond.b.end);

      assert(firstMonomer);
      assert(secondMonomer);

      center =
        firstMonomer.pp && secondMonomer.pp
          ? Vec2.centre(firstMonomer.pp, secondMonomer.pp)
          : bond.b.center;
    } else {
      center = bond.b.center;
    }

    if (center.x > x0 && center.x < x1 && center.y > y0 && center.y < y1) {
      bondList.push(bid);
    }
  });

  restruct.atoms.forEach((atom, aid) => {
    const relatedFGId = FunctionalGroup.findFunctionalGroupByAtom(
      functionalGroups,
      aid,
    );
    const sGroup = struct.sgroups.get(relatedFGId as number);

    if (struct.isAtomFromMacromolecule(aid)) {
      if (
        sGroup &&
        sGroup.pp &&
        sGroup.pp.x > x0 &&
        sGroup.pp.x < x1 &&
        sGroup.pp.y > y0 &&
        sGroup.pp.y < y1
      ) {
        atomList.push(aid);
      }
    } else {
      if (
        atom.a.pp.x > x0 &&
        atom.a.pp.x < x1 &&
        atom.a.pp.y > y0 &&
        atom.a.pp.y < y1 &&
        (!FunctionalGroup.isAtomInContractedFunctionalGroup(
          atom.a,
          sGroups,
          functionalGroups,
          true,
        ) ||
          aid === sGroup?.atoms[0])
      ) {
        atomList.push(aid);
      }
    }
  });

  const rxnArrowsList: Array<number> = [];
  const rxnPlusesList: Array<number> = [];
  const simpleObjectsList: Array<number> = [];

  // ReRxnArrow item doesn't have center method according to types but somehow it works
  restruct.rxnArrows.forEach((item: any, id) => {
    if (
      item.item.center().x > x0 &&
      item.item.center().x < x1 &&
      item.item.center().y > y0 &&
      item.item.center().y < y1
    ) {
      rxnArrowsList.push(id);
    }
  });

  restruct.rxnPluses.forEach((item, id) => {
    if (
      item.item.pp.x > x0 &&
      item.item.pp.x < x1 &&
      item.item.pp.y > y0 &&
      item.item.pp.y < y1
    ) {
      rxnPlusesList.push(id);
    }
  });

  restruct.simpleObjects.forEach((item, id) => {
    const referencePoints = item.getReferencePoints(true);
    const referencePointInRectangle = referencePoints.find(
      (point) => point.x > x0 && point.x < x1 && point.y > y0 && point.y < y1,
    );
    if (referencePointInRectangle) {
      simpleObjectsList.push(id);
    }
  });

  const enhancedFlagList: Array<number> = [];
  // ReEnhancedFlag doesn't have pp item according to types but somehow it works
  restruct.enhancedFlags.forEach((item: any, id) => {
    if (!item.pp) return;
    if (item.pp.x > x0 && item.pp.x < x1 && item.pp.y > y0 && item.pp.y < y1) {
      enhancedFlagList.push(id);
    }
  });

  const sgroupDataList: Array<number> = [];
  restruct.sgroupData.forEach((item, id) => {
    if (
      item.sgroup.pp.x > x0 &&
      item.sgroup.pp.x < x1 &&
      item.sgroup.pp.y > y0 &&
      item.sgroup.pp.y < y1
    ) {
      sgroupDataList.push(id);
    }
  });

  const textsList: Array<number> = [];
  restruct.texts.forEach((item, id) => {
    const referencePoints = item.getReferencePoints();
    const referencePointInRectangle = referencePoints.find((point) => {
      return point.x > x0 && point.x < x1 && point.y > y0 && point.y < y1;
    });

    if (referencePointInRectangle) {
      textsList.push(id);
    }
  });

  const rgroupAttachmentPointList: number[] = [];
  restruct.visibleRGroupAttachmentPoints.forEach((item, id) => {
    if (
      item.middlePoint.x > x0 &&
      item.middlePoint.x < x1 &&
      item.middlePoint.y > y0 &&
      item.middlePoint.y < y1
    ) {
      rgroupAttachmentPointList.push(id);
    }
  });

  const reImages = Array.from(restruct.images.entries()).reduce(
    (acc: Array<number>, [id, item]): Array<number> => {
      const isPointInside = Object.values(
        item.image.getReferencePositions(),
      ).some((point) => point.isInsidePolygon(polygon));
      return isPointInside ? acc.concat(id) : acc;
    },
    [],
  );

  const reMultitailArrows = Array.from(
    restruct.multitailArrows.entries(),
  ).reduce((acc: Array<number>, [id, item]): Array<number> => {
    const isPointInside = item.multitailArrow
      .getReferencePositionsArray()
      .some((point) => point.isInsidePolygon(polygon));
    return isPointInside ? acc.concat(id) : acc;
  }, []);

  return {
    atoms: atomList,
    bonds: bondList,
    rxnArrows: rxnArrowsList,
    rxnPluses: rxnPlusesList,
    enhancedFlags: enhancedFlagList,
    sgroupData: sgroupDataList,
    simpleObjects: simpleObjectsList,
    texts: textsList,
    rgroupAttachmentPoints: rgroupAttachmentPointList,
    [IMAGE_KEY]: reImages,
    [MULTITAIL_ARROW_KEY]: reMultitailArrows,
  };
}