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);
}