function getElementsInPolygon()

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


function getElementsInPolygon(restruct: ReStruct, rr) {
  // eslint-disable-line max-statements
  const bondList: Array<number> = [];
  const atomList: Array<number> = [];
  const r: any = [];
  const sGroups = restruct.sgroups;
  const functionalGroups = restruct.molecule.functionalGroups;
  const struct: Struct = restruct.molecule;

  for (let i = 0; i < rr.length; ++i) {
    r[i] = new Vec2(rr[i].x, rr[i].y);
  }

  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 (isPointInPolygon(r, center)) {
      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 && isPointInPolygon(r, sGroup.pp)) {
        atomList.push(aid);
      }
    } else {
      if (
        isPointInPolygon(r, atom.a.pp) &&
        (!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> = [];
  const textsList: Array<number> = [];

  restruct.rxnArrows.forEach((item, id) => {
    const referencePoints = item.getReferencePoints();
    const referencePointInPolygon = referencePoints.find((point) =>
      isPointInPolygon(r, point),
    );
    if (referencePointInPolygon) {
      rxnArrowsList.push(id);
    }
  });

  restruct.rxnPluses.forEach((item, id) => {
    if (isPointInPolygon(r, item.item.pp)) {
      rxnPlusesList.push(id);
    }
  });

  restruct.simpleObjects.forEach((item, id) => {
    const referencePoints = item.getReferencePoints(true);
    const referencePointInPolygon = referencePoints.find((point) =>
      isPointInPolygon(r, point),
    );
    if (referencePointInPolygon) {
      simpleObjectsList.push(id);
    }
  });

  restruct.texts.forEach((item, id) => {
    const referencePoints = item.getReferencePoints();
    const referencePointInPolygon = referencePoints.find((point) =>
      isPointInPolygon(r, point),
    );

    if (referencePointInPolygon) {
      textsList.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 && isPointInPolygon(r, item.pp)) {
      enhancedFlagList.push(id);
    }
  });

  const sgroupDataList: Array<number> = [];
  restruct.sgroupData.forEach((item, id) => {
    if (isPointInPolygon(r, item.sgroup.pp)) {
      sgroupDataList.push(id);
    }
  });

  const rgroupAttachmentPointList: number[] = [];
  restruct.visibleRGroupAttachmentPoints.forEach((item, id) => {
    if (isPointInPolygon(r, item.middlePoint)) {
      rgroupAttachmentPointList.push(id);
    }
  });

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

  const reMultitailArrows = Array.from(
    restruct.multitailArrows.entries(),
  ).reduce((acc: Array<number>, [id, item]) => {
    const isPointInside = item.multitailArrow
      .getReferencePositionsArray()
      .some((point) => isPointInPolygon(r, point));
    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,
  };
}