diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 442a0ea127..7e548ec499 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -113,6 +113,7 @@ void Sketch::clear(void) param2geoelement.clear(); pDependencyGroups.clear(); + solverExtensions.clear(); // deleting the geometry copied into this sketch for (std::vector::iterator it = Geoms.begin(); it != Geoms.end(); ++it) @@ -378,7 +379,7 @@ bool Sketch::analyseBlockedConstraintDependentParameters(std::vector &block if (element != param2geoelement.end()) { - auto blockable = std::find(blockedGeoIds.begin(),blockedGeoIds.end(),element->second.first); + auto blockable = std::find(blockedGeoIds.begin(),blockedGeoIds.end(),std::get<0>(element->second)); if( blockable != blockedGeoIds.end()) { // This dependent parameter group contains at least one parameter that should be blocked, so added to the blockable list. @@ -432,6 +433,9 @@ void Sketch::clearTemporaryConstraints(void) void Sketch::calculateDependentParametersElements(void) { // initialize solve extensions to a know state + solverExtensions.resize(Geoms.size()); + + int i = 0; for(auto geo : Geoms) { if(!geo.geo->hasExtension(Sketcher::SolverGeometryExtension::getClassTypeId())) @@ -444,6 +448,9 @@ void Sketch::calculateDependentParametersElements(void) solvext->init(SolverGeometryExtension::Dependent); else solvext->init(SolverGeometryExtension::Independent); + + solverExtensions[i] = solvext; + i++; } for(auto param : pDependentParametersList) { @@ -452,24 +459,36 @@ void Sketch::calculateDependentParametersElements(void) auto element = param2geoelement.find(param); if (element != param2geoelement.end()) { + auto geoid = std::get<0>(element->second); + auto geopos = std::get<1>(element->second); auto solvext = std::static_pointer_cast( - Geoms[element->second.first].geo->getExtension(Sketcher::SolverGeometryExtension::getClassTypeId()).lock()); + Geoms[geoid].geo->getExtension(Sketcher::SolverGeometryExtension::getClassTypeId()).lock()); - switch(element->second.second) { + auto index = std::get<2>(element->second); + + switch(geopos) { case PointPos::none: - solvext->setEdge(SolverGeometryExtension::Dependent); + solvext->setEdge(index, SolverGeometryExtension::Dependent); break; case PointPos::start: - solvext->setStart(SolverGeometryExtension::Dependent); + if(index == 0) + solvext->setStartx(SolverGeometryExtension::Dependent); + else + solvext->setStarty(SolverGeometryExtension::Dependent); break; case PointPos::end: - solvext->setEnd(SolverGeometryExtension::Dependent); + if(index == 0) + solvext->setEndx(SolverGeometryExtension::Dependent); + else + solvext->setEndy(SolverGeometryExtension::Dependent); break; case PointPos::mid: - solvext->setMid(SolverGeometryExtension::Dependent); + if(index == 0) + solvext->setMidx(SolverGeometryExtension::Dependent); + else + solvext->setMidy(SolverGeometryExtension::Dependent); break; } - } } @@ -485,7 +504,7 @@ void Sketch::calculateDependentParametersElements(void) auto element = param2geoelement.find(groups[i][j]); if (element != param2geoelement.end()) { - pDependencyGroups[i].insert(element->second); + pDependencyGroups[i].insert(std::pair(std::get<0>(element->second),std::get<1>(element->second))); } } } @@ -539,6 +558,14 @@ std::set < std::pair< int, Sketcher::PointPos>> Sketch::getDependencyGroup(int g return group; } +std::shared_ptr Sketch::getSolverExtension(int geoId) const +{ + if(geoId >= 0 && geoId < int(solverExtensions.size())) + return solverExtensions[geoId]; + + return nullptr; +} + int Sketch::resetSolver() { clearTemporaryConstraints(); @@ -687,8 +714,8 @@ int Sketch::addPoint(const Part::GeomPoint &point, bool fixed) Geoms.push_back(def); if(!fixed) { - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start, 0)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start, 1)); } // return the position of the newly added geometry @@ -746,10 +773,10 @@ int Sketch::addLineSegment(const Part::GeomLineSegment &lineSegment, bool fixed) Geoms.push_back(def); if(!fixed) { - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace( std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); } // return the position of the newly added geometry @@ -824,15 +851,15 @@ int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed) GCSsys.addConstraintArcRules(a); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,2)); } // return the position of the newly added geometry @@ -924,17 +951,17 @@ int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool f GCSsys.addConstraintArcOfEllipseRules(a); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,2)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,3)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,4)); } // return the position of the newly added geometry @@ -1024,17 +1051,17 @@ int Sketch::addArcOfHyperbola(const Part::GeomArcOfHyperbola &hyperbolaSegment, GCSsys.addConstraintArcOfHyperbolaRules(a); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,2)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,3)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,4)); } @@ -1115,16 +1142,16 @@ int Sketch::addArcOfParabola(const Part::GeomArcOfParabola ¶bolaSegment, boo GCSsys.addConstraintArcOfParabolaRules(a); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p4.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p4.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p3.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p4.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p4.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a1), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,2)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(a2), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,3)); } // return the position of the newly added geometry @@ -1180,6 +1207,7 @@ int Sketch::addBSpline(const Part::GeomBSplineCurve &bspline, bool fixed) std::vector spoles; + int i=0; for(std::vector::const_iterator it = poles.begin(); it != poles.end(); ++it){ params.push_back(new double( (*it).x )); params.push_back(new double( (*it).y )); @@ -1191,8 +1219,8 @@ int Sketch::addBSpline(const Part::GeomBSplineCurve &bspline, bool fixed) spoles.push_back(p); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p.x), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p.y), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p.x), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none,i++)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p.y), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none,i++)); } } @@ -1204,7 +1232,7 @@ int Sketch::addBSpline(const Part::GeomBSplineCurve &bspline, bool fixed) sweights.push_back(params[params.size()-1]); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size(), Sketcher::PointPos::none,i++)); } } @@ -1286,10 +1314,10 @@ int Sketch::addBSpline(const Part::GeomBSplineCurve &bspline, bool fixed) if(!fixed) { // Note: Poles and weight parameters are emplaced above - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::start,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p2.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::end,1)); } // return the position of the newly added geometry @@ -1336,9 +1364,9 @@ int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed) Geoms.push_back(def); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(p1.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(r), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); } // return the position of the newly added geometry @@ -1400,11 +1428,11 @@ int Sketch::addEllipse(const Part::GeomEllipse &elip, bool fixed) Geoms.push_back(def); if(!fixed) { - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(c.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(c.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); - param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(c.x), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(c.y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::mid,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1X), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,0)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(f1Y), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,1)); + param2geoelement.emplace(std::piecewise_construct, std::forward_as_tuple(rmin), std::forward_as_tuple(Geoms.size()-1, Sketcher::PointPos::none,2)); } // return the position of the newly added geometry diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 3c9439a943..4ab0ff5d6d 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -36,7 +36,8 @@ namespace Sketcher { - + // Forward declarations + class SolverGeometryExtension; class SketcherExport Sketch :public Base::Persistence { @@ -117,6 +118,8 @@ public: public: std::set < std::pair< int, Sketcher::PointPos>> getDependencyGroup(int geoId, PointPos pos) const; + std::shared_ptr getSolverExtension(int geoId) const; + public: @@ -441,10 +444,13 @@ protected: std::vector pDependentParametersList; + // map of geoIds to corresponding solverextensions. This is useful when solved geometry is NOT to be assigned to the SketchObject + std::vector> solverExtensions; + std::vector < std::set < std::pair< int, Sketcher::PointPos>>> pDependencyGroups; - // this map is intended to convert a parameter (double *) into a GeoId/PointPos pair - std::map> param2geoelement; + // this map is intended to convert a parameter (double *) into a GeoId/PointPos and parameter number + std::map> param2geoelement; // solving parameters std::vector Parameters; // with memory allocation diff --git a/src/Mod/Sketcher/App/SolverGeometryExtension.cpp b/src/Mod/Sketcher/App/SolverGeometryExtension.cpp index 83305eb7eb..83c90b737b 100644 --- a/src/Mod/Sketcher/App/SolverGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/SolverGeometryExtension.cpp @@ -24,6 +24,8 @@ #include +#include + #include "SolverGeometryExtension.h" using namespace Sketcher; @@ -33,7 +35,6 @@ using namespace Sketcher; TYPESYSTEM_SOURCE(Sketcher::SolverGeometryExtension,Part::GeometryExtension) SolverGeometryExtension::SolverGeometryExtension(): - Edge(SolverGeometryExtension::Dependent), Start(SolverGeometryExtension::Dependent), Mid(SolverGeometryExtension::Dependent), End(SolverGeometryExtension::Dependent) @@ -68,3 +69,101 @@ PyObject * SolverGeometryExtension::getPyObject(void) THROWM(Base::NotImplementedError, "SolverGeometryExtension does not have a Python counterpart"); } +SolverGeometryExtension::PointParameterStatus SolverGeometryExtension::getPoint(Sketcher::PointPos pos) const { + if(pos==Sketcher::PointPos::start) + return getStartPoint(); + if(pos==Sketcher::PointPos::end) + return getEndPoint(); + if(pos==Sketcher::PointPos::mid) + return getMidPoint(); + + THROWM(Base::ValueError, "SolverGeometryExtension - getPoint: Edge is not a point"); +} + +void SolverGeometryExtension::notifyAttachment(Part::Geometry * geo) +{ + // maps type to number of solver parameters taken by the edge + static std::map edgeParamMap = { + {Part::GeomPoint::getClassTypeId(), 0}, + {Part::GeomLineSegment::getClassTypeId(), 0}, + {Part::GeomArcOfCircle::getClassTypeId(), 3}, + {Part::GeomCircle::getClassTypeId(), 1}, + {Part::GeomArcOfEllipse::getClassTypeId(), 5}, + {Part::GeomEllipse::getClassTypeId(), 3}, + {Part::GeomArcOfHyperbola::getClassTypeId(), 5}, + {Part::GeomArcOfParabola::getClassTypeId(), 4}, + {Part::GeomBSplineCurve::getClassTypeId(), 0} // is dynamic + }; + + GeometryType = geo->getTypeId(); + + auto result = edgeParamMap.find(GeometryType); + + if( result == edgeParamMap.end() ) + THROWM(Base::TypeError, "SolverGeometryExtension - notifyAttachment - Geometry not supported!!"); + + auto nedgeparams = (*result).second; + + if(nedgeparams>0) + Edge.init(nedgeparams); +} + +void SolverGeometryExtension::ensureType(const Base::Type & type) +{ + if(GeometryType != type) + THROWM(Base::TypeError, "SolverGeometryExtension - requested edge parameters do not match underlying type!"); +} + +SolverGeometryExtension::Point & SolverGeometryExtension::getPoint() +{ + ensureType(Part::GeomPoint::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::Line & SolverGeometryExtension::getLine() +{ + ensureType(Part::GeomLineSegment::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::Arc & SolverGeometryExtension::getArc() +{ + ensureType(Part::GeomArcOfCircle::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::Circle & SolverGeometryExtension::getCircle() +{ + ensureType(Part::GeomCircle::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::ArcOfEllipse & SolverGeometryExtension::getArcOfEllipse() +{ + ensureType(Part::GeomArcOfEllipse::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::Ellipse & SolverGeometryExtension::getEllipse() +{ + ensureType(Part::GeomEllipse::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::ArcOfHyperbola & SolverGeometryExtension::getArcOfHyperbola() +{ + ensureType(Part::GeomArcOfHyperbola::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::ArcOfParabola & SolverGeometryExtension::getArcOfParabola() +{ + ensureType(Part::GeomArcOfParabola::getClassTypeId()); + return static_cast(Edge); +} + +SolverGeometryExtension::BSpline & SolverGeometryExtension::getBSpline() +{ + ensureType(Part::GeomBSplineCurve::getClassTypeId()); + return static_cast(Edge); +} diff --git a/src/Mod/Sketcher/App/SolverGeometryExtension.h b/src/Mod/Sketcher/App/SolverGeometryExtension.h index aee0130132..38301255e5 100644 --- a/src/Mod/Sketcher/App/SolverGeometryExtension.h +++ b/src/Mod/Sketcher/App/SolverGeometryExtension.h @@ -26,6 +26,10 @@ #include #include +#include "GeoEnum.h" + +#include + namespace Sketcher { @@ -45,36 +49,244 @@ public: NumParameterStatus }; + class PointParameterStatus { + public: + PointParameterStatus(ParameterStatus status) {setStatus(status);} + PointParameterStatus(ParameterStatus statusx, ParameterStatus statusy) {setStatus(statusx, statusy);} + + PointParameterStatus(const PointParameterStatus &) = default; + PointParameterStatus & operator=(const PointParameterStatus &) = default; + PointParameterStatus(PointParameterStatus &&) = default; + PointParameterStatus & operator=(PointParameterStatus &&) = default; + + ParameterStatus getStatus() const { return (xstatus == Independent && ystatus == Independent)?Independent:Dependent;} + ParameterStatus getStatusx() const { return xstatus;} + ParameterStatus getStatusy() const { return ystatus;} + + bool isXDoF() {return xstatus == Dependent;} + bool isYDoF() {return ystatus == Dependent;} + + int getDoFs() { + bool xfree = isXDoF(); + bool yfree = isYDoF(); + + if(xfree && yfree) + return 2; + else if(xfree || yfree) + return 1; + else + return 0; + } + + void setStatus(ParameterStatus status) {xstatus=status; ystatus=status;} + void setStatus(ParameterStatus statusx, ParameterStatus statusy) {xstatus=statusx; ystatus=statusy;} + void setStatusx(ParameterStatus statusx) {xstatus=statusx;} + void setStatusy(ParameterStatus statusy) {ystatus=statusy;} + + private: + ParameterStatus xstatus; + ParameterStatus ystatus; + }; + + class EdgeParameterStatus + { + public: + EdgeParameterStatus() = default; + + void init(int nparams) { pstatus.resize(nparams, ParameterStatus::Dependent);} + + ParameterStatus getStatus() const { + return std::all_of(pstatus.begin(), pstatus.end(), [](const auto & v){ return v == Independent;})?Independent:Dependent; + } + + void setStatus(ParameterStatus status) { std::fill(pstatus.begin(), pstatus.end(), status);} + + void setStatus(int index, ParameterStatus status) { + if(index > int(pstatus.size())) + pstatus.resize(index+1,ParameterStatus::Dependent); + + pstatus.at(index) = status; + + }; + + protected: + std::vector pstatus; + + }; + + class Point : public EdgeParameterStatus + { + public: + Point() = default; + }; + + class Line : public EdgeParameterStatus + { + public: + Line() = default; + }; + + class Arc : public EdgeParameterStatus + { + public: + Arc() = default; + + ParameterStatus getRadiusStatus() const {return pstatus[0];} + ParameterStatus getStartParameter() const {return pstatus[1];} + ParameterStatus getEndParameter() const {return pstatus[2];} + }; + + class Circle : public EdgeParameterStatus + { + public: + Circle() = default; + + ParameterStatus getRadiusStatus() const {return pstatus[0];} + bool isRadiusDoF() const {return pstatus[0] == Dependent;} + }; + + class ArcOfEllipse : public EdgeParameterStatus + { + public: + ArcOfEllipse() = default; + + ParameterStatus getFocusXStatus() const {return pstatus[0];} + ParameterStatus getFocusYStatus() const {return pstatus[1];} + ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];} + ParameterStatus getStartParameter() const {return pstatus[3];} + ParameterStatus getEndParameter() const {return pstatus[4];} + + bool isFocusDoF() const {return pstatus[0] == Dependent || pstatus[1] == Dependent;} + bool isMinorRadiusDoF() const {return (pstatus[2] == Dependent);} + }; + + class Ellipse : public EdgeParameterStatus + { + public: + Ellipse() = default; + + ParameterStatus getFocusXStatus() const {return pstatus[0];} + ParameterStatus getFocusYStatus() const {return pstatus[1];} + ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];} + + bool isFocusDoF() const {return pstatus[0] == Dependent || pstatus[1] == Dependent;} + bool isMinorRadiusDoF() const {return (pstatus[2] == Dependent);} + }; + + class ArcOfHyperbola : public EdgeParameterStatus + { + public: + ArcOfHyperbola() = default; + + ParameterStatus getFocusXStatus() const {return pstatus[0];} + ParameterStatus getFocusYStatus() const {return pstatus[1];} + ParameterStatus getFocusMinorRadiusStatus() const {return pstatus[2];} + ParameterStatus getStartParameter() const {return pstatus[3];} + ParameterStatus getEndParameter() const {return pstatus[4];} + }; + + class ArcOfParabola : public EdgeParameterStatus + { + public: + ArcOfParabola() = default; + + ParameterStatus getFocusXStatus() const {return pstatus[0];} + ParameterStatus getFocusYStatus() const {return pstatus[1];} + }; + + class BSpline : public EdgeParameterStatus + { + public: + BSpline() = default; + + ParameterStatus getPoleXStatus(int poleindex) const + { + int npoles = pstatus.size() / 3; + + if(poleindex < npoles) + return pstatus[poleindex*2]; + + THROWM(Base::IndexError, "Pole index out of range") + + } + + ParameterStatus getPoleYStatus(int poleindex) const + { + int npoles = pstatus.size() / 3; + + if(poleindex < npoles) + return pstatus[poleindex*2+1]; + + THROWM(Base::IndexError, "Pole index out of range") + + } + + ParameterStatus getWeightStatus(int weightindex) const + { + int nweights = pstatus.size() / 3; + + if(weightindex < nweights) + return pstatus[nweights*2 + weightindex]; + + THROWM(Base::IndexError, "Weight index out of range") + } + }; + + SolverGeometryExtension(); - SolverGeometryExtension(long cid); virtual ~SolverGeometryExtension() override = default; virtual std::unique_ptr copy(void) const override; virtual PyObject *getPyObject(void) override; - SolverStatus getGeometry() const {return ( Edge == Independent && - Start == Independent && - End == Independent && - Mid == Independent) ? FullyConstraint : NotFullyConstraint;} + virtual void notifyAttachment(Part::Geometry * geo) override; - ParameterStatus getEdge() const {return Edge;} - void setEdge(ParameterStatus status) {Edge = status;} + SolverStatus getGeometry() const {return ( Edge.getStatus() == Independent && + Start.getStatus() == Independent && + End.getStatus() == Independent && + Mid.getStatus() == Independent) ? FullyConstraint : NotFullyConstraint;} - ParameterStatus getStart() const {return Start;} - void setStart(ParameterStatus status) {Start = status;} + ParameterStatus getEdge() const {return Edge.getStatus();} + Point & getPoint(); + Line & getLine(); + Arc & getArc(); + Circle & getCircle(); + ArcOfEllipse & getArcOfEllipse(); + Ellipse & getEllipse(); + ArcOfHyperbola & getArcOfHyperbola(); + ArcOfParabola & getArcOfParabola(); + BSpline & getBSpline(); + EdgeParameterStatus getEdgeParameters() {return Edge;} + void setEdge(ParameterStatus status) {Edge.setStatus(status);} + void setEdge(int paramindex, ParameterStatus status) {Edge.setStatus(paramindex,status);} - ParameterStatus getMid() const {return Mid;} - void setMid(ParameterStatus status) {Mid = status;} + ParameterStatus getStart() const {return Start.getStatus();} + PointParameterStatus getStartPoint() const {return Start;} + void setStart(ParameterStatus xstatus, ParameterStatus ystatus) {Start.setStatus(xstatus,ystatus);} + void setStartx(ParameterStatus xstatus) {Start.setStatusx(xstatus);} + void setStarty(ParameterStatus ystatus) {Start.setStatusy(ystatus);} - ParameterStatus getEnd() const {return End;} - void setEnd(ParameterStatus status) {End = status;} + ParameterStatus getMid() const {return Mid.getStatus();} + PointParameterStatus getMidPoint() const {return Mid;} + void setMid(ParameterStatus xstatus, ParameterStatus ystatus) {Mid.setStatus(xstatus,ystatus);} + void setMidx(ParameterStatus xstatus) {Mid.setStatusx(xstatus);} + void setMidy(ParameterStatus ystatus) {Mid.setStatusy(ystatus);} + + ParameterStatus getEnd() const {return End.getStatus();} + PointParameterStatus getEndPoint() const {return End;} + + void setEnd(ParameterStatus xstatus, ParameterStatus ystatus) {End.setStatus(xstatus,ystatus);} + void setEndx(ParameterStatus xstatus) {End.setStatusx(xstatus);} + void setEndy(ParameterStatus ystatus) {End.setStatusy(ystatus);} + + PointParameterStatus getPoint(Sketcher::PointPos pos) const; void init(ParameterStatus status) { - Edge = status; - Start = status; - Mid = status; - End = status; + Edge.setStatus(status); + Start.setStatus(status); + Mid.setStatus(status); + End.setStatus(status); } protected: @@ -83,11 +295,16 @@ protected: private: SolverGeometryExtension(const SolverGeometryExtension&) = default; + void ensureType(const Base::Type & type); + private: - ParameterStatus Edge; - ParameterStatus Start; - ParameterStatus Mid; - ParameterStatus End; + EdgeParameterStatus Edge; + + PointParameterStatus Start; + PointParameterStatus Mid; + PointParameterStatus End; + + Base::Type GeometryType; }; } //namespace Sketcher