bool RenderParamInterface::needsLayoutSub (BaseMolecule& mol) { QS_DEF(RedBlackSet<int>, atomsToIgnore); atomsToIgnore.clear(); for (int i = mol.multiple_groups.begin(); i < mol.multiple_groups.end(); i = mol.multiple_groups.next(i)) { const Array<int>& atoms = mol.multiple_groups[i].atoms; const Array<int>& patoms = mol.multiple_groups[i].parent_atoms; for (int j = 0; j < atoms.size(); ++j) atomsToIgnore.find_or_insert(atoms[j]); for (int j = 0; j < patoms.size(); ++j) if (atomsToIgnore.find(patoms[j])) atomsToIgnore.remove(patoms[j]); } for (int i = mol.vertexBegin(); i < mol.vertexEnd(); i = mol.vertexNext(i)) { if (atomsToIgnore.find(i)) continue; for (int j = mol.vertexNext(i); j < mol.vertexEnd(); j = mol.vertexNext(j)) { if (atomsToIgnore.find(j)) continue; const Vec3f& v = mol.getAtomXyz(i); const Vec3f& w = mol.getAtomXyz(j); Vec3f d; d.diff(v, w); d.z = 0; if (d.length() < 1e-3) return true; } } return false; }
float LSeg3f::distToPoint(const Vec3f &point, Vec3f *closest) const { if (_is_degenerate) { if (closest != 0) closest->copy(_beg); return Vec3f::dist(point, _beg); } Vec3f p; float t; p.diff(point, _beg); t = Vec3f::dot(p, _diff) / _length_sqr; if (t < 0.f) p.copy(_beg); else if (t > 1.f) p.copy(_end); else p.lineCombin(_beg, _diff, t); if (closest != 0) closest->copy(p); return Vec3f::dist(point, p); }
void Molecule3dConstraintsChecker::_cache (int idx) { if (_cache_v.find(idx) || _cache_l.find(idx) || _cache_p.find(idx)) return; const MC::Base &base = _constraints.at(idx); switch (base.type) { case MC::POINT_ATOM: { int atom_idx = ((const Molecule3dConstraints::PointByAtom &)base).atom_idx; _cache_v.insert(idx, _target->getAtomXyz(_mapping[atom_idx])); break; } case MC::POINT_DISTANCE: { const MC::PointByDistance &constr = (const MC::PointByDistance &)base; _cache(constr.beg_id); _cache(constr.end_id); const Vec3f &beg = _cache_v.at(constr.beg_id); const Vec3f &end = _cache_v.at(constr.end_id); Vec3f dir; dir.diff(end, beg); if (!dir.normalize()) throw Error("point-by-distance: degenerate case"); Vec3f res; res.lineCombin(beg, dir, constr.distance); _cache_v.insert(idx, res); break; } case MC::POINT_PERCENTAGE: { const MC::PointByPercentage &constr = (const MC::PointByPercentage &)base; _cache(constr.beg_id); _cache(constr.end_id); const Vec3f &beg = _cache_v.at(constr.beg_id); const Vec3f &end = _cache_v.at(constr.end_id); Vec3f dir; dir.diff(end, beg); if (!dir.normalize()) throw Error("point-by-percentage: degenerate case"); Vec3f res; res.lineCombin2(beg, 1.f - constr.percentage, end, constr.percentage); _cache_v.insert(idx, res); break; } case MC::POINT_NORMALE: { const MC::PointByNormale &constr = (const MC::PointByNormale &)base; _cache(constr.org_id); _cache(constr.norm_id); const Vec3f &org = _cache_v.at(constr.org_id); const Line3f &norm = _cache_l.at(constr.norm_id); Vec3f res; res.lineCombin(org, norm.dir, constr.distance); _cache_v.insert(idx, res); break; } case MC::POINT_CENTROID: { const MC::Centroid &constr = (const MC::Centroid &)base; Vec3f res; if (constr.point_ids.size() < 1) throw Error("centroid: have %d points", constr.point_ids.size()); for (int i = 0; i < constr.point_ids.size(); i++) { _cache(constr.point_ids[i]); const Vec3f &pt = _cache_v.at(constr.point_ids[i]); res.add(pt); } res.scale(1.f / constr.point_ids.size()); _cache_v.insert(idx, res); break; } case MC::LINE_NORMALE: { const MC::Normale &constr = (const MC::Normale &)base; _cache(constr.plane_id); _cache(constr.point_id); const Plane3f &plane = _cache_p.at(constr.plane_id); const Vec3f &point = _cache_v.at(constr.point_id); Vec3f projection; Line3f res; plane.projection(point, projection); res.dir.copy(plane.getNorm()); res.org.copy(projection); _cache_l.insert(idx, res); break; } case MC::LINE_BEST_FIT: { const MC::BestFitLine &constr = (const MC::BestFitLine &)base; if (constr.point_ids.size() < 2) throw Error("best fit line: only %d points", constr.point_ids.size()); QS_DEF(Array<Vec3f>, points); points.clear(); for (int i = 0; i < constr.point_ids.size(); i++) { _cache(constr.point_ids[i]); points.push(_cache_v.at(constr.point_ids[i])); } Line3f res; res.bestFit(points.size(), points.ptr(), 0); _cache_l.insert(idx, res); break; } case MC::PLANE_BEST_FIT: { const MC::BestFitPlane &constr = (const MC::BestFitPlane &)base; if (constr.point_ids.size() < 3) throw Error("best fit line: only %d points", constr.point_ids.size()); QS_DEF(Array<Vec3f>, points); points.clear(); for (int i = 0; i < constr.point_ids.size(); i++) { _cache(constr.point_ids[i]); points.push(_cache_v.at(constr.point_ids[i])); } Plane3f res; res.bestFit(points.size(), points.ptr(), 0); _cache_p.insert(idx, res); break; } case MC::PLANE_POINT_LINE: { const MC::PlaneByPoint &constr = (const MC::PlaneByPoint &)base; _cache(constr.point_id); _cache(constr.line_id); const Vec3f &point = _cache_v.at(constr.point_id); const Line3f &line = _cache_l.at(constr.line_id); Plane3f res; res.byPointAndLine(point, line); _cache_p.insert(idx, res); break; } default: throw Error("unknown constraint type %d", base.type); } }