from TestSketcher import SketcherTestCase
class SketcherSetFillet(SketcherTestCase):
- def runTest(self):
+ def test_fillet(self):
l1 = self.sketch.addLine(0, 0, 0, 1)
l2 = self.sketch.addLine(0, 1, 1, 1)
self.sketch.setCoincident(l1.endPoint(), l2.startPoint())
- self.sketch.setFillet([l1.endPoint()], 10.0)
+ self.sketch.setFillet(l1.endPoint())
+ model.do()
+
+ def test_fillet_with_radius(self):
+ l1 = self.sketch.addLine(10, 10, 30, 10)
+ l2 = self.sketch.addLine(10, 10, 30, 30)
+ self.sketch.setCoincident(l1.startPoint(), l2.startPoint())
+ self.sketch.setFilletWithRadius(l1.startPoint(), 10.0)
model.do()
if __name__ == "__main__":
- unittest.main()
\ No newline at end of file
+ unittest.main(verbosity=2)
\ No newline at end of file
sketch.setLength(top, "L")
sketch.setLength(left, "L")
- sketch.setFillet([left.endPoint()], 32)
+ sketch.setFilletWithRadius(left.endPoint(), 32)
model.do() #!!!
//--------------------------------------------------------------------------------------
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_ResultConstruction.h>
+#include <ModelHighAPI_Double.h>
#include <ModelHighAPI_Dumper.h>
#include <ModelHighAPI_RefAttr.h>
#include <ModelHighAPI_Selection.h>
}
std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFillet(
- const std::list<ModelHighAPI_RefAttr> & thePoints,
- const ModelHighAPI_Double & theRadius)
+ const ModelHighAPI_RefAttr & thePoint)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_Fillet::ID());
- fillAttribute(thePoints, aFeature->data()->refattrlist(SketchPlugin_Constraint::ENTITY_A()));
- fillAttribute(theRadius, aFeature->real(SketchPlugin_Constraint::VALUE()));
- aFeature->execute();
+ fillAttribute(thePoint, aFeature->data()->refattr(SketchPlugin_Fillet::FILLET_POINT_ID()));
+ apply(); // finish operation to remove Fillet feature correcly
return InterfacePtr(new ModelHighAPI_Interface(aFeature));
}
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFilletWithRadius(
+ const ModelHighAPI_RefAttr & thePoint,
+ const ModelHighAPI_Double & theRadius)
+{
+ CompositeFeaturePtr aSketch = compositeFeature();
+ int aNbSubs = aSketch->numberOfSubs();
+
+ // create fillet
+ InterfacePtr aFilletFeature = setFillet(thePoint);
+
+ // set radius for just created arc
+ FeaturePtr anArc = aSketch->subFeature(aNbSubs - 1);
+ if (anArc->getKind() == SketchPlugin_Arc::ID())
+ setRadius(ModelHighAPI_RefAttr(anArc->lastResult()), ModelHighAPI_Double(theRadius));
+
+ return aFilletFeature;
+}
+
std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setFixed(
const ModelHighAPI_RefAttr & theObject)
{
/// Set fillet
SKETCHAPI_EXPORT
std::shared_ptr<ModelHighAPI_Interface> setFillet(
- const std::list<ModelHighAPI_RefAttr> & thePoints,
+ const ModelHighAPI_RefAttr & thePoint);
+
+ /// Set fillet with additional radius constraint
+ SKETCHAPI_EXPORT
+ std::shared_ptr<ModelHighAPI_Interface> setFilletWithRadius(
+ const ModelHighAPI_RefAttr & thePoint,
const ModelHighAPI_Double & theRadius);
/// Set fixed
TestConstraintMiddlePoint.py
TestMultiRotation.py
TestMultiTranslation.py
+ TestFillet.py
TestRectangle.py
TestProjection.py
TestSplit.py
if (isUpdateFlushed)
Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+ // Calculate Fillet parameters if does not yet
+ if (!myBaseFeatures[0] || !myBaseFeatures[1])
+ calculateFilletParameters();
+
// Create arc feature.
FeaturePtr aFilletArc = sketch()->addFeature(SketchPlugin_Arc::ID());
aFeaturesToBeRemoved1.insert(aFeaturesToBeRemoved2.begin(), aFeaturesToBeRemoved2.end());
ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved1);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
// Update fillet edges.
recalculateAttributes(aFilletArc, SketchPlugin_Arc::START_ID(),
return AISObjectPtr();
}
- // Get fillet point.
- AttributeRefAttrPtr aPointRefAttr = refattr(FILLET_POINT_ID());
- if (!aPointRefAttr->isInitialized() || aPointRefAttr->isObject()) {
- return AISObjectPtr();
- }
- std::shared_ptr<GeomDataAPI_Point2D> aFilletPoint2D =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointRefAttr->attr());
- if (!aFilletPoint2D.get()) {
+ if (!calculateFilletParameters())
return AISObjectPtr();
- }
- // Obtain constraint coincidence for the fillet point.
- FeaturePtr aConstraintCoincidence;
- const std::set<AttributePtr>& aRefsList = aFilletPoint2D->owner()->data()->refsToMe();
- for(std::set<AttributePtr>::const_iterator anIt = aRefsList.cbegin();
- anIt != aRefsList.cend();
- ++anIt) {
- std::shared_ptr<ModelAPI_Attribute> anAttr = (*anIt);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
- if(aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
- AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
- AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
- if(anAttrRefA.get() && !anAttrRefA->isObject()) {
- AttributePtr anAttrA = anAttrRefA->attr();
- if(aFilletPoint2D == anAttrA) {
- aConstraintCoincidence = aFeature;
- break;
- }
- }
- if(anAttrRefB.get() && !anAttrRefB->isObject()) {
- AttributePtr anAttrB = anAttrRefB->attr();
- if(aFilletPoint2D == anAttrB) {
- aConstraintCoincidence = aFeature;
- break;
- }
- }
- }
- }
+ // Create arc for presentation.
+ std::shared_ptr<GeomAPI_Pnt> aCenterPnt(aSketch->to3D(myCenterXY->x(), myCenterXY->y()));
+ std::shared_ptr<GeomAPI_Pnt> aTangentPnt1(aSketch->to3D(myTangentXY1->x(),
+ myTangentXY1->y()));
+ std::shared_ptr<GeomAPI_Pnt> aTangentPnt2(aSketch->to3D(myTangentXY2->x(),
+ myTangentXY2->y()));
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+ std::shared_ptr<GeomAPI_Shape> anArcShape =
+ GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenterPnt, aTangentPnt1, aTangentPnt2, aNDir->dir());
- if(!aConstraintCoincidence.get()) {
- setError("Error: No coincident edges at selected point.");
- return AISObjectPtr();
+ AISObjectPtr anAISObject = thePrevious;
+ if(!anAISObject.get()) {
+ anAISObject = AISObjectPtr(new GeomAPI_AISObject);
}
+ anAISObject->createShape(anArcShape);
+ return anAISObject;
+}
- // Get coincide edges.
- std::set<FeaturePtr> anEdgeFeatures = getCoincides(aConstraintCoincidence);
- if(anEdgeFeatures.size() != 2) {
+bool SketchPlugin_Fillet::calculateFilletParameters()
+{
+ // Get fillet point.
+ AttributeRefAttrPtr aPointRefAttr = refattr(FILLET_POINT_ID());
+ if (!aPointRefAttr->isInitialized() || aPointRefAttr->isObject())
+ return false;
+ std::shared_ptr<GeomDataAPI_Point2D> aFilletPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointRefAttr->attr());
+ if (!aFilletPoint2D.get())
+ return false;
+
+ if (!findFeaturesContainingFilletPoint(aFilletPoint2D)) {
setError("Error: Selected point does not have two suitable edges for fillet.");
- return AISObjectPtr();
+ return false;
}
- FeaturePtr anEdgeFeature1, anEdgeFeature2;
- std::set<FeaturePtr>::iterator aLinesIt = anEdgeFeatures.begin();
- anEdgeFeature1 = *aLinesIt++;
- anEdgeFeature2 = *aLinesIt;
-
// Getting points located at 1/3 of edge length from fillet point.
std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt2d = aFilletPoint2D->pnt();
std::shared_ptr<GeomAPI_Pnt2d> aPnt1, aPnt2;
- getPointOnEdge(anEdgeFeature1, aFilletPnt2d, aPnt1);
- getPointOnEdge(anEdgeFeature2, aFilletPnt2d, aPnt2);
+ getPointOnEdge(myBaseFeatures[0], aFilletPnt2d, aPnt1);
+ getPointOnEdge(myBaseFeatures[1], aFilletPnt2d, aPnt2);
/// Getting distances.
- double aDistance1 = getProjectionDistance(anEdgeFeature2, aPnt1);
- double aDistance2 = getProjectionDistance(anEdgeFeature1, aPnt2);
+ double aDistance1 = getProjectionDistance(myBaseFeatures[1], aPnt1);
+ double aDistance2 = getProjectionDistance(myBaseFeatures[0], aPnt2);
// Calculate radius value for fillet.
double aRadius = aDistance1 < aDistance2 ? aDistance1 / 2.0 : aDistance2 / 2.0;
// Calculate arc attributes.
static const int aNbFeatures = 2;
- myBaseFeatures[0] = anEdgeFeature1;
- myBaseFeatures[1] = anEdgeFeature2;
// First pair of points relate to first feature, second pair - to second.
std::shared_ptr<GeomAPI_Pnt2d> aStartEndPnt[aNbFeatures * 2];
for (int i = 0; i < aNbFeatures; i++) {
aEndAttr = SketchPlugin_Arc::END_ID();
} else { // Wrong argument.
setError("Error: One of the points has wrong coincide feature");
- return AISObjectPtr();
+ return false;
}
myFeatAttributes[2*i] = aStartAttr;
aStartEndPnt[2*i] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
}
}
- calculateFilletCenter(anEdgeFeature1, anEdgeFeature2, aRadius,
+ calculateFilletCenter(myBaseFeatures[0], myBaseFeatures[1], aRadius,
myIsNotInversed, myCenterXY, myTangentXY1, myTangentXY2);
// Tangent directions of the features in coincident point.
myTangentXY1 = myTangentXY2;
myTangentXY2 = aTmp;
}
+ return true;
+}
- // Create arc for presentation.
- std::shared_ptr<GeomAPI_Pnt> aCenterPnt(aSketch->to3D(myCenterXY->x(), myCenterXY->y()));
- std::shared_ptr<GeomAPI_Pnt> aTangentPnt1(aSketch->to3D(myTangentXY1->x(),
- myTangentXY1->y()));
- std::shared_ptr<GeomAPI_Pnt> aTangentPnt2(aSketch->to3D(myTangentXY2->x(),
- myTangentXY2->y()));
- std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
- std::shared_ptr<GeomAPI_Shape> anArcShape =
- GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenterPnt, aTangentPnt1, aTangentPnt2, aNDir->dir());
-
- AISObjectPtr anAISObject = thePrevious;
- if(!anAISObject.get()) {
- anAISObject = AISObjectPtr(new GeomAPI_AISObject);
+bool SketchPlugin_Fillet::findFeaturesContainingFilletPoint(
+ std::shared_ptr<GeomDataAPI_Point2D> theFilletPoint)
+{
+ // Obtain constraint coincidence for the fillet point.
+ FeaturePtr aConstraintCoincidence;
+ const std::set<AttributePtr>& aRefsList = theFilletPoint->owner()->data()->refsToMe();
+ for(std::set<AttributePtr>::const_iterator anIt = aRefsList.cbegin();
+ anIt != aRefsList.cend();
+ ++anIt) {
+ std::shared_ptr<ModelAPI_Attribute> anAttr = (*anIt);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
+ if(aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr anAttrRefA =
+ aFeature->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A());
+ AttributeRefAttrPtr anAttrRefB =
+ aFeature->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_B());
+ if(anAttrRefA.get() && !anAttrRefA->isObject()) {
+ AttributePtr anAttrA = anAttrRefA->attr();
+ if(theFilletPoint == anAttrA) {
+ aConstraintCoincidence = aFeature;
+ break;
+ }
+ }
+ if(anAttrRefB.get() && !anAttrRefB->isObject()) {
+ AttributePtr anAttrB = anAttrRefB->attr();
+ if(theFilletPoint == anAttrB) {
+ aConstraintCoincidence = aFeature;
+ break;
+ }
+ }
+ }
}
- anAISObject->createShape(anArcShape);
- return anAISObject;
+
+ if(!aConstraintCoincidence.get())
+ return false;
+
+ // Get coincide edges.
+ std::set<FeaturePtr> anEdgeFeatures = getCoincides(aConstraintCoincidence);
+ std::set<FeaturePtr>::iterator aLinesIt = anEdgeFeatures.begin();
+ for (int i = 0; aLinesIt != anEdgeFeatures.end() && i < 2; ++aLinesIt, ++i)
+ myBaseFeatures[i] = *aLinesIt;
+
+ return myBaseFeatures[0] && myBaseFeatures[1];
}
// ========= Auxiliary functions =================
#include "SketchPlugin_SketchEntity.h"
#include <GeomAPI_IPresentable.h>
+#include <GeomDataAPI_Point2D.h>
class GeomAPI_XY;
/// \brief Use plugin manager for features creation
SketchPlugin_Fillet();
+private:
+ bool calculateFilletParameters();
+
+ bool findFeaturesContainingFilletPoint(std::shared_ptr<GeomDataAPI_Point2D> theFilletPoint);
+
private:
FeaturePtr myBaseFeatures[2];
std::string myFeatAttributes[4]; // attributes of features
"""
TestFillet.py
- Unit test of SketchPlugin_ConstraintFillet class
+ Unit test of SketchPlugin_Fillet class
- SketchPlugin_ConstraintFillet
- static const std::string MY_CONSTRAINT_FILLET_ID("SketchConstraintFillet");
+ SketchPlugin_Fillet
+ static const std::string MY_CONSTRAINT_FILLET_ID("SketchFillet");
data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttrList::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
#=========================================================================
# Auxiliary functions
#=========================================================================
-aStartPoint1 = []
+TOLERANCE = 1.e-7
def createSketch1(theSketch):
global aEndPoint1, aEndPoint2
# Initialize sketch by three lines with coincident boundaries
allFeatures = []
+
+ aSession.startOperation()
# Line1
aSketchLine1 = theSketch.addFeature("SketchLine")
aStartPoint1 = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint"))
aCoincidence2.refattr("ConstraintEntityA").setAttr(aEndPoint2)
aCoincidence2.refattr("ConstraintEntityB").setAttr(aStartPoint3)
- theSketch.execute()
+ aSession.finishOperation()
return allFeatures
global aStartPoint1
# Initialize sketch by line and arc with coincident boundary
allFeatures = []
+
+ aSession.startOperation()
# Line
aSketchLine = theSketch.addFeature("SketchLine")
aStartPoint1 = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
aCoincidence.refattr("ConstraintEntityA").setAttr(aStartPoint1)
aCoincidence.refattr("ConstraintEntityB").setAttr(aStartPoint2)
- theSketch.execute()
+ aSession.finishOperation()
return allFeatures
-def checkFillet(theObjects, theRadius):
- # Verify the arc and lines are connected smoothly
- print "Check Fillet"
- aLine = []
- anArc = []
- aSize = len(theObjects)
- for feat in theObjects:
- assert(feat is not None)
- if (feat.getKind() == "SketchLine"):
- aLine.append(feat)
- elif (feat.getKind() == "SketchArc"):
- anArc.append(feat)
- aFilletArc = anArc[-1]
- assert(aFilletArc is not None)
- anArc.pop()
-
- anArcPoints = []
- aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcStartPoint"))
- #print "ArcStartPoint " + repr(aPoint.x()) + " " + repr(aPoint.y())
- anArcPoints.append((aPoint.x(), aPoint.y()))
- aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcEndPoint"))
- #print "ArcEndPoint " + repr(aPoint.x()) + " " + repr(aPoint.y())
- anArcPoints.append((aPoint.x(), aPoint.y()))
- aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcCenter"))
- #print "ArcCenter " + repr(aPoint.x()) + " " + repr(aPoint.y())
- aCenterX = aPoint.x()
- aCenterY = aPoint.y()
- aFilletRadius = math.hypot(anArcPoints[0][0]-aCenterX, anArcPoints[0][1]-aCenterY)
-
- for line in aLine:
- aStartPoint = geomDataAPI_Point2D(line.attribute("StartPoint"))
- aEndPoint = geomDataAPI_Point2D(line.attribute("EndPoint"))
-
- aLinePoints = []
- aLinePoints.append((aStartPoint.x(), aStartPoint.y()))
- #print "aLineStartPoint " + repr(aStartPoint.x()) + " " + repr(aStartPoint.y())
- aLinePoints.append((aEndPoint.x(), aEndPoint.y()))
- #print "aLineEndPoint " + repr(aEndPoint.x()) + " " + repr(aEndPoint.y())
-
- aLineDirX = aEndPoint.x() - aStartPoint.x()
- aLineDirY = aEndPoint.y() - aStartPoint.y()
-
- for arcPt in anArcPoints:
- for linePt in aLinePoints:
- if (math.hypot(linePt[0]-arcPt[0], linePt[1]-arcPt[1]) < 1.e-10):
- aDirX = linePt[0] - aCenterX
- aDirY = linePt[1] - aCenterY
- assert(math.fabs(math.hypot(aDirX, aDirY) - theRadius) < 1.e-7)
- aDot = aDirX * aLineDirX + aDirY * aLineDirY
-
- break;
-
- if (aSize == 3):
- for arc in anArc:
- aStartPoint = geomDataAPI_Point2D(arc.attribute("ArcStartPoint"))
- aEndPoint = geomDataAPI_Point2D(arc.attribute("ArcEndPoint"))
- aCenterPoint = geomDataAPI_Point2D(arc.attribute("ArcCenter"))
-
- aBaseArcPoints = []
- aBaseArcPoints.append((aStartPoint.x(), aStartPoint.y()))
- #print "anArcStartPoint " + repr(aStartPoint.x()) + " " + repr(aStartPoint.y())
- aBaseArcPoints.append((aEndPoint.x(), aEndPoint.y()))
- #print "anArcEndPoint " + repr(aEndPoint.x()) + " " + repr(aEndPoint.y())
- #print "anArcCenter " + repr(aCenterPoint.x()) + " " + repr(aCenterPoint.y())
-
- aRadius = math.hypot(aStartPoint.x()-aCenterPoint.x(), aStartPoint.y()-aCenterPoint.y())
- aDist = math.hypot(aCenterPoint.x() - aCenterX, aCenterPoint.y() - aCenterY)
- assert math.fabs(aFilletRadius + aRadius - aDist) < 1.e-7 or math.fabs(math.fabs(aFilletRadius - aRadius) - aDist) < 1.e-7, \
- "Fillet radius = {0}, Base arc radius = {1}, distance between centers = {2}".format(aFilletRadius, aRadius, aDist)
+def checkSmoothness(theSketch):
+ aPtPtCoincidences = getCoincidences(theSketch)
+ for coinc in aPtPtCoincidences:
+ aConnectedFeatures = connectedFeatures(coinc)
+ assert(len(aConnectedFeatures) == 2)
+ if aConnectedFeatures[0].getKind() == "SketchArc":
+ if aConnectedFeatures[1].getKind() == "SketchArc":
+ checkArcArcSmoothness(aConnectedFeatures[0], aConnectedFeatures[1])
+ elif aConnectedFeatures[1].getKind() == "SketchLine":
+ checkArcLineSmoothness(aConnectedFeatures[0], aConnectedFeatures[1])
+ elif aConnectedFeatures[0].getKind() == "SketchLine" and aConnectedFeatures[1].getKind() == "SketchArc":
+ checkArcLineSmoothness(aConnectedFeatures[1], aConnectedFeatures[0])
+
+def checkArcLineSmoothness(theArc, theLine):
+ aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
+ aDistance = distancePointLine(aCenter, theLine)
+ aRadius = arcRadius(theArc)
+ assert(math.fabs(aRadius - aDistance) < TOLERANCE)
+
+def checkArcArcSmoothness(theArc1, theArc2):
+ aCenter1 = geomDataAPI_Point2D(theArc1.attribute("ArcCenter"))
+ aCenter2 = geomDataAPI_Point2D(theArc2.attribute("ArcCenter"))
+ aDistance = distancePointPoint(aCenter1, aCenter2)
+ aRadius1 = arcRadius(theArc1)
+ aRadius2 = arcRadius(theArc2)
+ aRadSum = aRadius1 + aRadius2
+ aRadDiff = math.fabs(aRadius1 - aRadius2)
+ assert(math.fabs(aDistance - aRadSum) < TOLERANCE or math.fabs(aDistance - aRadDiff) < TOLERANCE)
+
+def getCoincidences(theSketch):
+ aCoincidences = []
+ for anIndex in range(0, theSketch.numberOfSubs()):
+ aSubFeature = theSketch.subFeature(anIndex)
+ if aSubFeature.getKind == "SketchConstraintCoincidence":
+ anEntityA = aSubFeature.refattr("ConstraintEntityA")
+ anEntityB = aSubFeature.refattr("ConstraintEntityB")
+ if not anEntityA.isObject() and not anEntityB.isObject():
+ aCoincidences.append(aSubFeature)
+ return aCoincidences
+
+def connectedFeatures(theCoincidence):
+ anEntityA = aSubFeature.refattr("ConstraintEntityA")
+ anEntityB = aSubFeature.refattr("ConstraintEntityB")
+ return [anEntityA.attr().owner(), anEntityB.attr().owner()]
+
+def arcRadius(theArc):
+ aCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter"))
+ aStart = geomDataAPI_Point2D(theArc.attribute("ArcStartPoint"))
+ return distancePointPoint(aCenter, aStart)
+
+def distancePointPoint(thePoint1, thePoint2):
+ return math.hypot(thePoint1.x() - thePoint2.x(), thePoint1.y() - thePoint2.y())
+
+def distancePointLine(thePoint, theLine):
+ aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
+ aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
+ aLength = distancePointPoint(aLineStart, aLineEnd)
+
+ aDir1x, aDir1y = aLineEnd.x() - aLineStart.x(), aLineEnd.y() - aLineStart.y()
+ aDir2x, aDir2y = thePoint.x() - aLineStart.x(), thePoint.y() - aLineStart.y()
+ aCross = aDir1x * aDir2y - aDir1y * aDir2x
+ return math.fabs(aCross) / aLength
#=========================================================================
#=========================================================================
# Initialize sketch by three connected lines
#=========================================================================
-aSession.startOperation()
-aFeaturesList = createSketch1(aSketchFeature)
-aSession.finishOperation()
-aSketchSubFeatures = []
-for aSubIndex in range(0, aSketchFeature.numberOfSubs()):
- aSketchSubFeatures.append(aSketchFeature.subFeature(aSubIndex))
+createSketch1(aSketchFeature)
assert (model.dof(aSketchFeature) == 8)
#=========================================================================
-# Global variables
-#=========================================================================
-FILLET_RADIUS1 = 3.
-FILLET_RADIUS2 = 5.
-#=========================================================================
# Create the Fillet
#=========================================================================
aSession.startOperation()
-aFillet = aSketchFeature.addFeature("SketchConstraintFillet")
-aRefAttrA = aFillet.data().refattrlist("ConstraintEntityA");
-aRefAttrA.append(aEndPoint1)
-aRefAttrA.append(aEndPoint2)
-aRadius = aFillet.real("ConstraintValue")
-aRadius.setValue(FILLET_RADIUS1)
-aFillet.execute()
-aResObjects = []
-for aSubIndex in range(0, aSketchFeature.numberOfSubs()):
- aSubFeature = aSketchFeature.subFeature(aSubIndex)
- if aSubFeature not in aSketchSubFeatures:
- if aSubFeature.getKind() == "SketchLine":
- aResObjects.insert(0, aSubFeature)
- elif aSubFeature.getKind() == "SketchArc":
- aResObjects.append(aSubFeature)
+aFillet = aSketchFeature.addFeature("SketchFillet")
+aFillet.refattr("fillet_point").setAttr(aEndPoint1);
+aSession.finishOperation()
+aSession.startOperation()
+aFillet = aSketchFeature.addFeature("SketchFillet")
+aFillet.refattr("fillet_point").setAttr(aEndPoint2);
+aSession.finishOperation()
#=========================================================================
# Verify the objects of fillet are created
#=========================================================================
-assert(aResObjects)
-checkFillet(aResObjects, FILLET_RADIUS1)
-assert model.dof(aSketchFeature) == 8, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 10, observed = {0}".format(model.dof(aSketchFeature))
-#=========================================================================
-# Change Fillet radius
-#=========================================================================
-aRadius.setValue(FILLET_RADIUS2)
-aFillet.execute()
-aSession.finishOperation()
-checkFillet(aResObjects, FILLET_RADIUS2)
-assert model.dof(aSketchFeature) == 8, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 10, observed = {0}".format(model.dof(aSketchFeature))
+checkSmoothness(aSketchFeature)
+assert model.dof(aSketchFeature) == 14, "PlaneGCS limitation: if you see this message, then maybe PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 10, observed = {0}".format(model.dof(aSketchFeature))
#=========================================================================
# Create another sketch
#=========================================================================
# Initialize sketch by line and arc
#=========================================================================
-aSession.startOperation()
-aFeaturesList = createSketch2(aSketchFeature)
-aSession.finishOperation()
-aSketchSubFeatures = []
-for aSubIndex in range(0, aSketchFeature.numberOfSubs()):
- aSketchSubFeatures.append(aSketchFeature.subFeature(aSubIndex))
+createSketch2(aSketchFeature)
assert (model.dof(aSketchFeature) == 7)
#=========================================================================
# Create the Fillet
#=========================================================================
aSession.startOperation()
-aFillet = aSketchFeature.addFeature("SketchConstraintFillet")
-aRefAttrA = aFillet.data().refattrlist("ConstraintEntityA");
-aRefAttrA.append(aStartPoint1)
-aRadius = aFillet.real("ConstraintValue")
-aRadius.setValue(FILLET_RADIUS1)
-aFillet.execute()
-aResObjects = []
-for aSubIndex in range(0, aSketchFeature.numberOfSubs()):
- aSubFeature = aSketchFeature.subFeature(aSubIndex)
- if aSubFeature not in aSketchSubFeatures:
- if aSubFeature.getKind() == "SketchLine":
- aResObjects.insert(0, aSubFeature)
- elif aSubFeature.getKind() == "SketchArc":
- aResObjects.append(aSubFeature)
+aFillet = aSketchFeature.addFeature("SketchFillet")
+aFillet.refattr("fillet_point").setAttr(aStartPoint1)
+aSession.finishOperation()
#=========================================================================
# Verify the objects of fillet are created
#=========================================================================
-assert(aResObjects)
-checkFillet(aResObjects, FILLET_RADIUS1)
-assert model.dof(aSketchFeature) == 7, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 8, observed = {0}".format(model.dof(aSketchFeature))
-#=========================================================================
-# Change Fillet radius
-#=========================================================================
-aRadius.setValue(FILLET_RADIUS2)
-aFillet.execute()
-aSession.finishOperation()
-checkFillet(aResObjects, FILLET_RADIUS2)
-assert model.dof(aSketchFeature) == 11, "PlaneGCS limitation: if you see this message, then PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 8, observed = {0}".format(model.dof(aSketchFeature))
+checkSmoothness(aSketchFeature)
+assert model.dof(aSketchFeature) == 10, "PlaneGCS limitation: if you see this message, then maybe PlaneGCS has solved DoF for sketch with fillet correctly (expected DoF = 8, observed = {0}".format(model.dof(aSketchFeature))
#=========================================================================
# End of test
#=========================================================================
<boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
</feature>
- <!-- SketchConstraintFillet -->
+ <!-- SketchFillet -->
<feature id="SketchFillet"
title="Fillet"
tooltip="Create constraint defining fillet between two objects"
}
SolveStatus aStatus;
- if (aResult == GCS::Success) {
+ if (aResult == GCS::Failed)
+ aStatus = STATUS_FAILED;
+ else {
myEquationSystem->applySolution();
if (myDOF < 0)
myDOF = myEquationSystem->dofsNumber();
aStatus = STATUS_OK;
- } else
- aStatus = STATUS_FAILED;
+ }
return aStatus;
}
{
GCSConstraintPtr aNewConstr;
if (theType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
+ GCSCurvePtr anEntCirc, anEntLine;
+ if (theEntity1->type() == ENTITY_LINE) {
+ anEntLine = theEntity1->entity();
+ anEntCirc = theEntity2->entity();
+ } else {
+ anEntLine = theEntity2->entity();
+ anEntCirc = theEntity1->entity();
+ }
+
std::shared_ptr<GCS::Circle> aCirc =
- std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::dynamic_pointer_cast<GCS::Circle>(anEntCirc);
std::shared_ptr<GCS::Line> aLine =
- std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+ std::dynamic_pointer_cast<GCS::Line>(anEntLine);
aNewConstr =
GCSConstraintPtr(new GCS::ConstraintP2LDistance(aCirc->center, *aLine, aCirc->rad));
// Check the quantity of entities of each type and their order (arcs first)
int aNbLines = 0;
int aNbCircles = 0;
- bool isSwap = false; // whether need to swap arguments (arc goes before line)
std::vector<EntityWrapperPtr>::iterator anEntIt = theAttributes.begin() + 2;
for (; anEntIt != theAttributes.end(); ++anEntIt) {
if ((*anEntIt)->type() == ENTITY_LINE)
++aNbLines;
- else if ((*anEntIt)->type() == ENTITY_ARC || (*anEntIt)->type() == ENTITY_CIRCLE) {
+ else if ((*anEntIt)->type() == ENTITY_ARC || (*anEntIt)->type() == ENTITY_CIRCLE)
++aNbCircles;
- isSwap = aNbLines > 0;
- }
}
if (aNbCircles < 1) {
if (!hasSingleCoincidence(aFeature1, aFeature2))
myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
}
-
- if (isSwap) {
- EntityWrapperPtr aTemp = theAttributes[2];
- theAttributes[2] = theAttributes[3];
- theAttributes[3] = aTemp;
- }
}
void SketchSolver_ConstraintTangent::adjustConstraint()