Extend Perpendicular constraint to make orthogonal arc and line.
TestConstraintMiddlePoint.py
TestConstraintParallel.py
TestConstraintPerpendicular.py
+ TestConstraintPerpendicularArcLine.py
TestConstraintRadius.py
TestConstraintRadiusFailure.py
TestConstraintTangent.py
new SketchPlugin_ExternalValidator);
aFactory->registerValidator("SketchPlugin_TangentAttr",
new SketchPlugin_TangentAttrValidator);
+ aFactory->registerValidator("SketchPlugin_PerpendicularAttr",
+ new SketchPlugin_PerpendicularAttrValidator);
aFactory->registerValidator("SketchPlugin_NotFixed",
new SketchPlugin_NotFixedValidator);
aFactory->registerValidator("SketchPlugin_EqualAttr",
return true;
}
+bool SketchPlugin_PerpendicularAttrValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
+ theError = "The attribute with the %1 type is not processed";
+ theError.arg(theAttribute->attributeType());
+ return false;
+ }
+
+ std::string aParamA = theArguments.front();
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
+ FeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+
+ bool isObject = aRefAttr->isObject();
+ ObjectPtr anObject = aRefAttr->object();
+ if (isObject && anObject.get()) {
+ FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
+
+ AttributeRefAttrPtr aOtherAttr = anOwner->refattr(aParamA);
+ ObjectPtr aOtherObject = aOtherAttr->object();
+ FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
+ if (!aOtherFea)
+ return true;
+
+ // at least one feature should be a line
+ if (aRefFea->getKind() != SketchPlugin_Line::ID() &&
+ aOtherFea->getKind() != SketchPlugin_Line::ID()) {
+ theError = "At least one feature should be a line";
+ return false;
+ }
+ }
+ else {
+ theError = "It uses an empty object";
+ return false;
+ }
+
+ return true;
+}
+
bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_PerpendicularAttrValidator
+ * \ingroup Validators
+ * \brief Validator for the perpendicular constraint input.
+ *
+ * Checks that two arcs are not selected for perpendicular.
+ */
+class SketchPlugin_PerpendicularAttrValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ //! \param theError error message
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
/**\class SketchPlugin_NotFixedValidator
* \ingroup Validators
--- /dev/null
+# Copyright (C) 2019 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-35, -10, 20)
+SketchLine_1 = Sketch_1.addLine(-21, 2, 24, 21)
+SketchLine_2 = Sketch_1.addLine(24, 21, 20, -30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchArc_1 = Sketch_1.addArc(25, -30, 42, -34, 13, -17.31142245955048, False)
+model.do()
+
+# check error on perpendicularity of circle and arc
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchCircle_1.results()[1], SketchArc_1.results()[1])
+model.do()
+assert(SketchConstraintPerpendicular_1.feature().error() != "")
+
+# avoid the failure
+Part_1_doc.removeFeature(SketchConstraintPerpendicular_1.feature())
+model.do()
+assert(Sketch_1.feature().error() == "")
+
+# set correct constraints
+SketchConstraintPerpendicular_2 = Sketch_1.setPerpendicular(SketchCircle_1.results()[1], SketchLine_1.result())
+SketchConstraintPerpendicular_3 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchArc_1.results()[1])
+model.do()
+
+TOLERANCE = 1.e-7
+assert(model.distancePointLine(SketchCircle_1.center(), SketchLine_1) < TOLERANCE)
+assert(model.distancePointLine(SketchArc_1.center(), SketchLine_2) < TOLERANCE)
+model.end()
+
+assert(model.checkPythonDump())
<!-- SketchConstraintPerpendicular -->
<feature id="SketchConstraintPerpendicular" title="Perpendicular"
- tooltip="Create constraint defining two perpendicular lines"
+ tooltip="Create constraint defining two orthogonal objects"
icon="icons/Sketch/perpendicular.png"
helpfile="perpendicularFeature.html">
<sketch_shape_selector id="ConstraintEntityA"
- label="First line" tooltip="Select a line"
+ label="First object" tooltip="Select line or arc"
shape_types="edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
- <validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityB"/>
+ <validator id="GeomValidators_ShapeType" parameters="line,circle"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
- label="Second line" tooltip="Select a line"
+ label="Second object" tooltip="Select line or arc"
shape_types="edge">
- <validator id="PartSet_DifferentObjects"/>
+ <validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
- <validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityA"/>
+ <validator id="GeomValidators_ShapeType" parameters="line,circle"/>
</sketch_shape_selector>
<validator id="PartSet_PerpendicularSelection"/>
</feature>
{
std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
- GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
+
+ std::shared_ptr<GCS::Circle> aCirc1 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::shared_ptr<GCS::Circle> aCirc2 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
+
+ GCSConstraintPtr aNewConstr;
+ if (aLine1 && aLine2)
+ aNewConstr.reset(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
+ else {
+ if (aLine1 && aCirc2)
+ aCirc1 = aCirc2;
+ else if (aLine2 && aCirc1)
+ aLine1 = aLine2;
+
+ aNewConstr.reset(new GCS::ConstraintPointOnLine(aCirc1->center, *aLine1));
+ }
return ConstraintWrapperPtr(
new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
#include <GeomAPI_Curve.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Lin.h>
+#include <GeomAPI_Vertex.h>
IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Perpendicular, SketcherPrs_SymbolPrs);
GeomEdgePtr aEdge1(new GeomAPI_Edge(aShp1));
GeomEdgePtr aEdge2(new GeomAPI_Edge(aShp2));
- std::shared_ptr<GeomAPI_Lin> aLin1 = aEdge1->line();
- std::shared_ptr<GeomAPI_Lin> aLin2 = aEdge2->line();
-
- std::shared_ptr<GeomAPI_Pnt> aPnt = aLin1->intersect(aLin2);
- double aParam1 = aLin1->projParam(aPnt);
- double aParam2 = aLin2->projParam(aPnt);
-
- GeomAPI_Curve aCurve1(aShp1);
- GeomAPI_Curve aCurve2(aShp2);
- bool isInside1 = (aParam1 >= (aCurve1.startParam() - Precision::Confusion())) &&
- (aParam1 <= (aCurve1.endParam() + Precision::Confusion()));
- bool isInside2 = (aParam2 >= (aCurve2.startParam() - Precision::Confusion())) &&
- (aParam2 <= (aCurve2.endParam() + Precision::Confusion()));
-
- if (!(isInside1 && isInside2))
- aPnt = std::shared_ptr<GeomAPI_Pnt>();
+ GeomShapePtr anInter = aEdge1->intersect(aEdge2);
+ std::shared_ptr<GeomAPI_Pnt> aPnt;
+ if (anInter && anInter->isVertex())
+ aPnt = anInter->vertex()->point();
// Compute position of symbols
SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();