geom_points = [geom.Pnt2d(*p) for p in points]
left, top_left, top_middle, top_right, right, bottom, = sketch.addPolygon(*geom_points)
- points = [(l + r, H), (l, H), (l + 2 * r, H)]
+ points = [(l + r, H), (l + 2 * r, H), (l, H)]
points = [(p[0], -p[1]) for p in points] # as we look to back of the face
center, start, end = [geom.Pnt2d(*p) for p in points]
arc = sketch.addArc(center, start, end)
#=========================================================================
# Auxiliary functions
#=========================================================================
+def normalize(theDir):
+ aLen = math.hypot(theDir[0], theDir[1])
+ if aLen < 1.e-10:
+ aLen = 1.0
+ return [theDir[0] / aLen, theDir[1] / aLen]
+
def checkMirror(theListInit, theListMirr, theMirrorLine):
- TOL = 1.e-8
+ TOL = 5.e-5
aListSize = theListInit.size()
aLineStartPoint = geomDataAPI_Point2D(theMirrorLine.attribute("StartPoint"))
aLineEndPoint = geomDataAPI_Point2D(theMirrorLine.attribute("EndPoint"))
- aLineDirX = aLineEndPoint.x() - aLineStartPoint.x()
- aLineDirY = aLineEndPoint.y() - aLineStartPoint.y()
+ aLineDir = [aLineEndPoint.x() - aLineStartPoint.x(), aLineEndPoint.y() - aLineStartPoint.y()]
+ aLineDir = normalize(aLineDir)
for ind in range(0, aListSize):
aFeatureB = ModelAPI_Feature.feature(theListInit.object(ind))
for key in anAttributes:
aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
- aDirX = aPointC.x() - aPointB.x()
- aDirY = aPointC.y() - aPointB.y()
- aDot = aLineDirX * aDirX + aLineDirY * aDirY
+ aDir = [aPointC.x() - aPointB.x(), aPointC.y() - aPointB.y()]
+ aDir = normalize(aDir)
+ aDot = aLineDir[0] * aDir[0] + aLineDir[1] * aDir[1]
assert math.fabs(aDot) < TOL, "aDot = {0}".format(aDot)
aDirX = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
aDirY = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
- aCross = aLineDirX * aDirY - aLineDirY * aDirX
+ aCross = aLineDir[0] * aDir[0] - aLineDir[1] * aDir[1]
assert math.fabs(aCross) < TOL, "aCross = {0}".format(aCross)
aTangency.execute()
aSession.finishOperation()
-assert(math.fabs(distancePointLine(aCircleCenter, aLine) - aCircleRadius.value()) < 1.e-10)
+assert(math.fabs(distancePointLine(aCircleCenter, aLine) - round(aCircleRadius.value(), 5)) < 1.e-10)
#=========================================================================
# End of test
#=========================================================================
ydiff = math.pow((thePointA.y() - thePointB.y()), 2)
return round(math.sqrt(xdiff + ydiff), 5)
+def dot(thePoint11, thePoint12, thePoint21, thePoint22):
+ """
+ subroutine to calculate dit product between lines given by their points
+ """
+ aDirX1 = thePoint12.x() - thePoint11.x()
+ aDirY1 = thePoint12.y() - thePoint11.y()
+ aLen1 = math.hypot(aDirX1, aDirY1)
+ aDirX2 = thePoint22.x() - thePoint21.x()
+ aDirY2 = thePoint22.y() - thePoint21.y()
+ aLen2 = math.hypot(aDirX2, aDirY2)
+ aDot = aDirX1 * aDirX2 + aDirY1 * aDirY2
+ return aDot / aLen1 / aLen2
+
aSession = ModelAPI_Session.get()
aDocument = aSession.moduleDocument()
anArcEndPoint.setValue(100., 25.)
aSession.finishOperation()
anArcCenter = geomDataAPI_Point2D(aSketchArcTangent.attribute("ArcCenter"))
-assert(anArcCenter.x() == 50.)
+aDot = dot(anArcCenter, aLineEnd, aLineStart, aLineEnd)
+assert math.fabs(aDot) <= 2.e-4, "Observed dot product: {0}".format(aDot)
#=========================================================================
# Create an arc, tangent to the previous arc
#=========================================================================
new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
aConstrList.push_back(GCSConstraintPtr(
new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
+ // update value of intermediate parameter
+ double x = *aLine1->p1.x - *aLine1->p2.x;
+ double y = *aLine1->p1.y - *aLine1->p2.y;
+ double aLen = sqrt(x*x + y*y);
+ theIntermed->setValue(aLen);
} else {
std::shared_ptr<GCS::Circle> aCirc1 =
std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
bool PlaneGCSSolver_Storage::isRedundant(
GCSConstraintPtr theCheckedConstraint,
- ConstraintWrapperPtr theParentConstraint) const
+ ConstraintWrapperPtr theParentConstraint,
+ std::list<std::set<double*> >& theCoincidentPoints) const
{
if (theParentConstraint->type() == CONSTRAINT_SYMMETRIC) {
if (theCheckedConstraint->getTypeId() == GCS::Perpendicular) {
}
}
else if (theParentConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT) {
- // Mark constraint redundant if the coincident points both are slaves in the list of stored coincidences
- const std::list<EntityWrapperPtr>& aPoints = theParentConstraint->entities();
- CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
- for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt) {
- if (aCoincIt->second.find(aPoints.front()) != aCoincIt->second.end() &&
- aCoincIt->second.find(aPoints.back()) != aCoincIt->second.end())
+ // Verify that the coincidence between points is already added
+ GCS::VEC_pD aParams = theCheckedConstraint->params();
+
+ std::list<std::set<double*> >::iterator aCoincIt, aFound1, aFound2;
+ aFound1 = aFound2 = theCoincidentPoints.end();
+ for (aCoincIt = theCoincidentPoints.begin(); aCoincIt != theCoincidentPoints.end(); ++aCoincIt) {
+ if (aFound1 == theCoincidentPoints.end() && aCoincIt->find(aParams[0]) != aCoincIt->end())
+ aFound1 = aCoincIt;
+ if (aFound2 == theCoincidentPoints.end() && aCoincIt->find(aParams[1]) != aCoincIt->end())
+ aFound2 = aCoincIt;
+ if (aFound1 != theCoincidentPoints.end() && aFound2 != theCoincidentPoints.end())
+ break;
+ }
+ if (aCoincIt != theCoincidentPoints.end()) { // both point are found
+ if (aFound1 == aFound2)
return true;
+ // merge two groups of coincidence
+ aFound1->insert(aFound2->begin(), aFound2->end());
+ theCoincidentPoints.erase(aFound2);
+ } else {
+ if (aFound1 != theCoincidentPoints.end())
+ aFound1->insert(aParams[1]);
+ else if (aFound2 != theCoincidentPoints.end())
+ aFound2->insert(aParams[0]);
+ else {
+ std::set<double*> aNewCoincidence;
+ aNewCoincidence.insert(aParams[0]);
+ aNewCoincidence.insert(aParams[1]);
+ theCoincidentPoints.push_back(aNewCoincidence);
+ }
}
}
std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
aCIt = myConstraintMap.begin();
GCS::SET_I aTangentIDs;
+ std::list<std::set<double*> > aCoincidentPoints;
for (; aCIt != myConstraintMap.end(); ++aCIt) {
std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
for (; anIt != aGCS->constraints().end(); ++anIt)
- if (!isRedundant(*anIt, aGCS))
+ if (!isRedundant(*anIt, aGCS, aCoincidentPoints))
aSolver->addConstraint(*anIt);
}
// store IDs of tangent constraints to avoid incorrect report of redundant constraints
///
/// This is a workaround method to avoid some kinds of conflicting constraints:
/// * symmetric of two points placed on the mirror line (do not add perpendicular constraint)
- bool isRedundant(GCSConstraintPtr theCheckedConstraint, ConstraintWrapperPtr theParentConstraint) const;
+ bool isRedundant(GCSConstraintPtr theCheckedConstraint,
+ ConstraintWrapperPtr theParentConstraint,
+ std::list<std::set<double*> >& theCoincidentPoints = std::list<std::set<double*> >() ) const;
private:
GCS::VEC_pD myParameters; ///< list of parameters