void Molecule3dConstraints::_buildSub()

in core/indigo-core/molecule/src/molecule_3d_constraints.cpp [92:431]


void Molecule3dConstraints::_buildSub(PtrArray<Base>& sub, const PtrArray<Base>& super, const int* mapping)
{
    QS_DEF(Array<int>, cmapping); // mapping of constraints from supermolecule to submolecule
    int i, j;

    cmapping.resize(super.size());
    for (i = 0; i < super.size(); i++)
        cmapping[i] = -1;

    sub.clear();

    do
    {
        for (i = 0; i < super.size(); i++)
        {
            int oldsize = sub.size();

            if (cmapping[i] >= 0)
                continue;

            const Base& base = *super.at(i);

            switch (base.type)
            {
            case POINT_ATOM: {
                int atom_idx = ((const Molecule3dConstraints::PointByAtom&)base).atom_idx;

                if (mapping[atom_idx] < 0)
                    continue;

                std::unique_ptr<PointByAtom> newconstr = std::make_unique<PointByAtom>();
                newconstr->atom_idx = mapping[atom_idx];

                sub.add(newconstr.release());
                break;
            }
            case POINT_DISTANCE: {
                const PointByDistance& constr = (const PointByDistance&)base;

                int beg_id = cmapping[constr.beg_id];
                int end_id = cmapping[constr.end_id];

                if (beg_id < 0 || end_id < 0)
                    continue;

                std::unique_ptr<PointByDistance> newconstr = std::make_unique<PointByDistance>();
                newconstr->beg_id = beg_id;
                newconstr->end_id = end_id;
                newconstr->distance = constr.distance;

                sub.add(newconstr.release());
                break;
            }
            case POINT_PERCENTAGE: {
                const PointByPercentage& constr = (const PointByPercentage&)base;

                int beg_id = cmapping[constr.beg_id];
                int end_id = cmapping[constr.end_id];

                if (beg_id < 0 || end_id < 0)
                    continue;

                std::unique_ptr<PointByPercentage> newconstr = std::make_unique<PointByPercentage>();
                newconstr->beg_id = beg_id;
                newconstr->end_id = end_id;
                newconstr->percentage = constr.percentage;
                sub.add(newconstr.release());
                break;
            }
            case POINT_NORMALE: {
                const PointByNormale& constr = (const PointByNormale&)base;

                int org_id = cmapping[constr.org_id];
                int norm_id = cmapping[constr.norm_id];

                if (org_id < 0 || norm_id < 0)
                    continue;

                std::unique_ptr<PointByNormale> newconstr = std::make_unique<PointByNormale>();
                newconstr->norm_id = norm_id;
                newconstr->org_id = org_id;
                newconstr->distance = constr.distance;
                sub.add(newconstr.release());
                break;
            }
            case POINT_CENTROID: {
                const Centroid& constr = (const Centroid&)base;

                std::unique_ptr<Centroid> newconstr = std::make_unique<Centroid>();

                for (j = 0; j < constr.point_ids.size(); j++)
                {
                    int pt_idx = cmapping[constr.point_ids[j]];

                    if (pt_idx < 0)
                        break;

                    newconstr->point_ids.push(pt_idx);
                }

                if (newconstr->point_ids.size() < constr.point_ids.size())
                    continue;

                sub.add(newconstr.release());
                break;
            }
            case LINE_NORMALE: {
                const Normale& constr = (const Normale&)base;

                int plane_id = cmapping[constr.plane_id];
                int point_id = cmapping[constr.point_id];

                if (plane_id < 0 || point_id < 0)
                    continue;

                std::unique_ptr<Normale> newconstr = std::make_unique<Normale>();
                newconstr->plane_id = plane_id;
                newconstr->point_id = point_id;

                sub.add(newconstr.release());
                break;
            }
            case LINE_BEST_FIT: {
                const BestFitLine& constr = (const BestFitLine&)base;

                std::unique_ptr<BestFitLine> newconstr = std::make_unique<BestFitLine>();
                for (j = 0; j < constr.point_ids.size(); j++)
                {
                    int pt_idx = cmapping[constr.point_ids[j]];

                    if (pt_idx < 0)
                        break;

                    newconstr->point_ids.push(pt_idx);
                }

                if (newconstr->point_ids.size() < constr.point_ids.size())
                    continue;

                newconstr->max_deviation = constr.max_deviation;
                sub.add(newconstr.release());
                break;
            }
            case PLANE_BEST_FIT: {
                const BestFitPlane& constr = (const BestFitPlane&)base;

                std::unique_ptr<BestFitPlane> newconstr = std::make_unique<BestFitPlane>();
                for (j = 0; j < constr.point_ids.size(); j++)
                {
                    int pt_idx = cmapping[constr.point_ids[j]];

                    if (pt_idx < 0)
                        break;

                    newconstr->point_ids.push(pt_idx);
                }

                if (newconstr->point_ids.size() < constr.point_ids.size())
                    continue;

                newconstr->max_deviation = constr.max_deviation;
                sub.add(newconstr.release());
                break;
            }
            case PLANE_POINT_LINE: {
                const PlaneByPoint& constr = (const PlaneByPoint&)base;

                int point_id = cmapping[constr.point_id];
                int line_id = cmapping[constr.line_id];

                if (line_id < 0 || point_id < 0)
                    continue;

                std::unique_ptr<PlaneByPoint> newconstr = std::make_unique<PlaneByPoint>();
                newconstr->line_id = line_id;
                newconstr->point_id = point_id;
                sub.add(newconstr.release());
                break;
            }
            case ANGLE_3POINTS: {
                const AngleByPoints& constr = (const AngleByPoints&)base;

                int point1_id = cmapping[constr.point1_id];
                int point2_id = cmapping[constr.point2_id];
                int point3_id = cmapping[constr.point3_id];

                if (point1_id < 0 || point2_id < 0 || point3_id < 0)
                    continue;

                std::unique_ptr<AngleByPoints> newconstr = std::make_unique<AngleByPoints>();
                newconstr->point1_id = point1_id;
                newconstr->point2_id = point2_id;
                newconstr->point3_id = point3_id;

                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case ANGLE_2LINES: {
                const AngleByLines& constr = (const AngleByLines&)base;

                int line1_id = cmapping[constr.line1_id];
                int line2_id = cmapping[constr.line2_id];

                if (line1_id < 0 || line2_id < 0)
                    continue;

                std::unique_ptr<AngleByLines> newconstr = std::make_unique<AngleByLines>();
                newconstr->line1_id = line1_id;
                newconstr->line2_id = line2_id;

                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case ANGLE_2PLANES: {
                const AngleByPlanes& constr = (const AngleByPlanes&)base;

                int plane1_id = cmapping[constr.plane1_id];
                int plane2_id = cmapping[constr.plane2_id];

                if (plane1_id < 0 || plane2_id < 0)
                    continue;

                std::unique_ptr<AngleByPlanes> newconstr = std::make_unique<AngleByPlanes>();
                newconstr->plane1_id = plane1_id;
                newconstr->plane2_id = plane2_id;

                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case ANGLE_DIHEDRAL: {
                const AngleDihedral& constr = (const AngleDihedral&)base;

                int point1_id = cmapping[constr.point1_id];
                int point2_id = cmapping[constr.point2_id];
                int point3_id = cmapping[constr.point3_id];
                int point4_id = cmapping[constr.point4_id];

                if (point1_id < 0 || point2_id < 0 || point3_id < 0 || point4_id < 0)
                    continue;

                std::unique_ptr<AngleDihedral> newconstr = std::make_unique<AngleDihedral>();
                newconstr->point1_id = point1_id;
                newconstr->point2_id = point2_id;
                newconstr->point3_id = point3_id;
                newconstr->point4_id = point4_id;

                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case DISTANCE_2POINTS: {
                const DistanceByPoints& constr = (const DistanceByPoints&)base;

                int beg_id = cmapping[constr.beg_id];
                int end_id = cmapping[constr.end_id];

                if (beg_id < 0 || end_id < 0)
                    continue;

                std::unique_ptr<DistanceByPoints> newconstr = std::make_unique<DistanceByPoints>();
                newconstr->beg_id = beg_id;
                newconstr->end_id = end_id;
                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case DISTANCE_POINT_LINE: {
                const DistanceByLine& constr = (const DistanceByLine&)base;

                int point_id = cmapping[constr.point_id];
                int line_id = cmapping[constr.line_id];

                if (line_id < 0 || point_id < 0)
                    continue;

                std::unique_ptr<DistanceByLine> newconstr = std::make_unique<DistanceByLine>();
                newconstr->line_id = line_id;
                newconstr->point_id = point_id;
                newconstr->top = constr.top;
                newconstr->bottom = constr.bottom;
                sub.add(newconstr.release());
                break;
            }
            case DISTANCE_POINT_PLANE: {
                const DistanceByPlane& constr = (const DistanceByPlane&)base;

                int plane_id = cmapping[constr.plane_id];
                int point_id = cmapping[constr.point_id];

                if (plane_id < 0 || point_id < 0)
                    continue;

                std::unique_ptr<DistanceByPlane> newconstr = std::make_unique<DistanceByPlane>();
                newconstr->plane_id = plane_id;
                newconstr->point_id = point_id;
                newconstr->bottom = constr.bottom;
                newconstr->top = constr.top;
                sub.add(newconstr.release());
                break;
            }
            case EXCLUSION_SPHERE: {
                const ExclusionSphere& constr = (const ExclusionSphere&)base;

                int center_id = cmapping[constr.center_id];

                if (center_id < 0)
                    continue;

                std::unique_ptr<ExclusionSphere> newconstr = std::make_unique<ExclusionSphere>();
                for (j = 0; j < constr.allowed_atoms.size(); j++)
                {
                    int atom_idx = mapping[constr.allowed_atoms[j]];

                    if (atom_idx >= 0)
                        newconstr->allowed_atoms.push(atom_idx);
                }

                newconstr->center_id = center_id;
                newconstr->allow_unconnected = constr.allow_unconnected;
                newconstr->radius = constr.radius;
                sub.add(newconstr.release());
                break;
            }
            default:
                throw Error("build on submolecule: unknown feature %d", base.type);
            }
            cmapping[i] = oldsize;
        }
        if (i == super.size())
            break;
    } while (1);
}