const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
double aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve((const TopoDS_Edge&)aShape, aFirst, aLast);
- if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)) && aCurve->IsClosed())
- return true;
+ if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)))
+ {
+ // Check the difference of first and last parameters to be equal to the curve period
+ if (Abs(aLast - aFirst - aCurve->Period()) < Precision::PConfusion())
+ return true;
+ }
return false;
}
const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
double aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve((const TopoDS_Edge&)aShape, aFirst, aLast);
- if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)) && !aCurve->IsClosed())
- return true;
+ if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)))
+ {
+ // Check the difference of first and last parameters is not equal the curve period
+ if (Abs(aLast - aFirst - aCurve->Period()) >= Precision::PConfusion())
+ return true;
+ }
return false;
}
SketchPlugin_ConstraintHorizontal.h
SketchPlugin_ConstraintVertical.h
SketchPlugin_ConstraintEqual.h
+ SketchPlugin_ConstraintTangent.h
SketchPlugin_ShapeValidator.h
SketchPlugin_Validators.h
SketchPlugin_ResultValidators.h
SketchPlugin_ConstraintHorizontal.cpp
SketchPlugin_ConstraintVertical.cpp
SketchPlugin_ConstraintEqual.cpp
+ SketchPlugin_ConstraintTangent.cpp
SketchPlugin_ShapeValidator.cpp
SketchPlugin_Validators.cpp
SketchPlugin_ResultValidators.cpp
TestConstraintConcidence.py
TestConstraintLength.py
TestConstraintDistance.py
- TestConstraintParallel.py
+# TestConstraintParallel.py
TestConstraintPerpendicular.py
TestConstraintRadius.py
TestConstraintRigid.py
TestConstraintHorizontal.py
TestConstraintVertical.py
TestConstraintEqual.py
+ TestConstraintTangent.py
+ TestConstraintParallel.py
TestHighload.py
TestSnowflake.py)
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_ConstraintTangent.cpp
+// Created: 16 Mar 2015
+// Author: Artem ZHIDKOV
+
+#include "SketchPlugin_ConstraintTangent.h"
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <SketcherPrs_Factory.h>
+
+#include <Config_PropManager.h>
+
+SketchPlugin_ConstraintTangent::SketchPlugin_ConstraintTangent()
+{
+}
+
+void SketchPlugin_ConstraintTangent::initAttributes()
+{
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type());
+}
+
+void SketchPlugin_ConstraintTangent::execute()
+{
+}
+
+AISObjectPtr SketchPlugin_ConstraintTangent::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = thePrevious;
+ /// TODO: Tangency constraint presentation should be put here
+ return anAIS;
+}
+
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_ConstraintTangent.h
+// Created: 16 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_ConstraintTangent_H_
+#define SketchPlugin_ConstraintTangent_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_ConstraintTangent
+ * \ingroup Plugins
+ * \brief Feature for creation of a new constraint tangency between line and arc
+ * or between two circular arcs. The used features must have shared vertex
+ *
+ * This constraint has two attributes:
+ * SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B()
+ */
+class SketchPlugin_ConstraintTangent : public SketchPlugin_ConstraintBase
+{
+ public:
+ /// Equal constraint kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_TANGENT_ID("SketchConstraintTangent");
+ return MY_CONSTRAINT_TANGENT_ID;
+ }
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_ConstraintTangent::ID();
+ return MY_KIND;
+ }
+
+ /// \brief Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Returns the AIS preview
+ SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintTangent();
+};
+
+#endif
#include <SketchPlugin_ConstraintPerpendicular.h>
#include <SketchPlugin_ConstraintRadius.h>
#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_ConstraintVertical.h>
#include <SketchPlugin_Validators.h>
#include <SketchPlugin_ResultValidators.h>
return FeaturePtr(new SketchPlugin_ConstraintVertical);
} else if (theFeatureID == SketchPlugin_ConstraintEqual::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintEqual);
+ } else if (theFeatureID == SketchPlugin_ConstraintTangent::ID()) {
+ return FeaturePtr(new SketchPlugin_ConstraintTangent);
}
// feature of such kind is not found
return FeaturePtr();
aMsg->setState(SketchPlugin_ConstraintHorizontal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintVertical::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintEqual::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_ConstraintTangent::ID(), aHasSketchPlane);
}
}
return aMsg;
--- /dev/null
+"""
+ TestConstraintTangent.py
+ Unit test of SketchPlugin_ConstraintTangent class
+
+ SketchPlugin_ConstraintTangent
+ static const std::string MY_CONSTRAINT_TANGENT_ID("SketchConstraintTangent");
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::type());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::type());
+
+"""
+from GeomDataAPI import *
+from GeomAPI import *
+from ModelAPI import *
+import math
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+
+__updated__ = "2015-03-17"
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = modelAPI_CompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+diry = geomDataAPI_Dir(aSketchFeature.attribute("DirY"))
+diry.setValue(0, 1, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+#=========================================================================
+# Creation of an arc and a line
+#=========================================================================
+# Arc
+aSession.startOperation()
+aSketchArc1 = aSketchFeature.addFeature("SketchArc")
+anArcCentr = geomDataAPI_Point2D(aSketchArc1.attribute("ArcCenter"))
+anArcCentr.setValue(10., 10.)
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcStartPoint"))
+anArcStartPoint.setValue(0., 50.)
+anArcEndPoint = geomDataAPI_Point2D(aSketchArc1.attribute("ArcEndPoint"))
+anArcEndPoint.setValue(50., 0.)
+aSession.finishOperation()
+# Line
+aSession.startOperation()
+aSketchLine1 = aSketchFeature.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aSketchLine1.attribute("StartPoint"))
+aLineEndPoint = geomDataAPI_Point2D(aSketchLine1.attribute("EndPoint"))
+aLineStartPoint.setValue(0., 50.)
+aLineEndPoint.setValue(0., 100.)
+aSession.finishOperation()
+#=========================================================================
+# Link arc start point and line's point by the coincidence constraint
+#=========================================================================
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(anArcStartPoint)
+reflistB.setAttr(aLineStartPoint)
+aConstraint.execute()
+aSession.finishOperation()
+#=========================================================================
+# Add tangency constraint and check correctness
+#=========================================================================
+aSession.startOperation()
+aTangency = aSketchFeature.addFeature("SketchConstraintTangent")
+aRefObjectA = aTangency.refattr("ConstraintEntityA")
+aRefObjectB = aTangency.refattr("ConstraintEntityB")
+anObjectA = modelAPI_ResultConstruction(aSketchArc1.firstResult())
+anObjectB = modelAPI_ResultConstruction(aSketchLine1.firstResult())
+assert (anObjectA is not None)
+assert (anObjectB is not None)
+aRefObjectA.setObject(anObjectA)
+aRefObjectB.setObject(anObjectB)
+aTangency.execute()
+aSession.finishOperation()
+anArcVecX = anArcStartPoint.x() - anArcCentr.x()
+anArcVecY = anArcStartPoint.y() - anArcCentr.y()
+aLineVecX = aLineEndPoint.x() - aLineStartPoint.x()
+aLineVecY = aLineEndPoint.y() - aLineStartPoint.y()
+aDot = anArcVecX * aLineVecX + anArcVecY * aLineVecY
+print anArcVecX, anArcVecY
+print aLineVecX, aLineVecY
+print aDot
+print aLineStartPoint.x(), aLineStartPoint.y(), aLineEndPoint.x(), aLineEndPoint.y()
+assert(aDot == 0.)
+#=========================================================================
+# End of test
+#=========================================================================
<group id="Basic">
<feature
id="Sketch"
- nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual"
+ nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent"
when_nested="accept abort"
title="Sketch"
tooltip="Create a new sketch"
label="Last object" tooltip="Select line, circle or arc" shape_types="edge">
</sketch_constraint_shape_selector>
</feature>
+ <!-- SketchConstraintTangent -->
+ <feature id="SketchConstraintTangent" title="Tangent" tooltip="Create constraint defining tangency of two objects">
+ <sketch_constraint_shape_selector id="ConstraintEntityA"
+ label="First object" tooltip="Select line or arc" shape_types="edge">
+ </sketch_constraint_shape_selector>
+
+ <sketch_constraint_shape_selector id="ConstraintEntityB"
+ label="Last object" tooltip="Select line or arc" shape_types="edge">
+ </sketch_constraint_shape_selector>
+ </feature>
</group>
</workbench>
</plugin>
#include <SketchPlugin_ConstraintPerpendicular.h>
#include <SketchPlugin_ConstraintRadius.h>
#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_ConstraintVertical.h>
#include <ModelAPI_AttributeRefAttr.h>
std::shared_ptr<ModelAPI_Attribute> anAttr =
aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
AttrType aType = typeOfAttribute(anAttr);
- if (aType == LINE)
- {
+ if (aType == LINE) {
myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
aNbLines++;
}
return getType();
}
+ if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0)
+ {
+ static const int anArcPosDefault = 2;
+ static const int aLinePosDefault = 3;
+ int anArcPos = anArcPosDefault; // arc in tangency constraint should be placed before line
+ int aLinePos = aLinePosDefault;
+ for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+ std::shared_ptr<ModelAPI_Attribute> anAttr =
+ aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+ AttrType aType = typeOfAttribute(anAttr);
+ if (aType == LINE && aLinePos < CONSTRAINT_ATTR_SIZE)
+ myAttributesList[aLinePos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+ else if (aType == ARC)
+ myAttributesList[anArcPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+ }
+ if (anArcPos - anArcPosDefault + aLinePos - aLinePosDefault == 2)
+ myType = aLinePos > 3 ? SLVS_C_ARC_LINE_TANGENT : SLVS_C_CURVE_CURVE_TANGENT;
+ return getType();
+ }
+
/// \todo Implement other kind of constraints
return getType();
static const std::string MY_ERROR_VALUE("Conflicting constraints");
return MY_ERROR_VALUE;
}
+ /// The entities need to have shared point, but they have not
+ inline static const std::string& NO_COINCIDENT_POINTS()
+ {
+ static const std::string MY_ERROR_VALUE("Objects should have coincident point");
+ return MY_ERROR_VALUE;
+ }
};
/// This value is used to give unique index to the groups
removeTemporaryConstraints(aTmpConstrToDelete);
}
}
+ // For the tangency constraints it is necessary to identify which points of entities are coincident
+ int aSlvsOtherFlag = 0;
+ int aSlvsOther2Flag = 0;
+ if (aConstrType == SLVS_C_ARC_LINE_TANGENT || aConstrType == SLVS_C_CURVE_CURVE_TANGENT) {
+ // Search entities used by constraint
+ int anEnt1Pos = Search(aConstrEnt[2], myEntities);
+ int anEnt2Pos = Search(aConstrEnt[3], myEntities);
+ // Obtain start and end points of entities
+ Slvs_hEntity aPointsToFind[4];
+ aPointsToFind[0] = myEntities[anEnt1Pos].point[1];
+ aPointsToFind[1]= myEntities[anEnt1Pos].point[2];
+ bool hasLine = (myEntities[anEnt2Pos].type == SLVS_E_LINE_SEGMENT);
+ aPointsToFind[2]= myEntities[anEnt2Pos].point[hasLine ? 0 : 1];
+ aPointsToFind[3]= myEntities[anEnt2Pos].point[hasLine ? 1 : 2];
+ // Search coincident points
+ bool isPointFound[4];
+ std::vector<std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+ for ( ; aCPIter != myCoincidentPoints.end(); aCPIter++) {
+ for (int i = 0; i < 4; i++)
+ isPointFound[i] = (aCPIter->find(aPointsToFind[i]) != aCPIter->end());
+ if ((isPointFound[0] || isPointFound[1]) && (isPointFound[2] || isPointFound[3])) {
+ // the arc is tangent by end point
+ if (isPointFound[1]) aSlvsOtherFlag = 1;
+ // the second item is an arc and it is tangent by end point too
+ if (!hasLine && isPointFound[3]) aSlvsOther2Flag = 1;
+ break;
+ }
+ }
+ if (aCPIter == myCoincidentPoints.end()) {
+ // There is no coincident points between tangential objects. Generate error message
+ Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this);
+ return false;
+ }
+ }
// Create SolveSpace constraint structure
- Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
+ Slvs_Constraint aSlvsConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
myWorkplane.h, aDistance, aConstrEnt[0],
aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]);
- myConstraints.push_back(aConstraint);
- myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aConstraint.h);
- int aConstrPos = Search(aConstraint.h, myConstraints);
+ if (aSlvsOtherFlag != 0) aSlvsConstr.other = aSlvsOtherFlag;
+ if (aSlvsOther2Flag != 0) aSlvsConstr.other2 = aSlvsOther2Flag;
+ myConstraints.push_back(aSlvsConstr);
+ myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>(1, aSlvsConstr.h);
+ int aConstrPos = Search(aSlvsConstr.h, myConstraints);
aConstrIter = myConstraints.begin() + aConstrPos;
myNeedToSolve = true;
} else { // Attributes of constraint may be changed => update constraint