Implement feature to compute length, distance, radius or angle.
FeaturesAPI_ExtrusionBoolean.h
FeaturesAPI_Fillet.h
FeaturesAPI_Intersection.h
+ FeaturesAPI_Measurement.h
FeaturesAPI_MultiRotation.h
FeaturesAPI_MultiTranslation.h
FeaturesAPI_Partition.h
FeaturesAPI_ExtrusionBoolean.cpp
FeaturesAPI_Fillet.cpp
FeaturesAPI_Intersection.cpp
+ FeaturesAPI_Measurement.cpp
FeaturesAPI_MultiRotation.cpp
FeaturesAPI_MultiTranslation.cpp
FeaturesAPI_Partition.cpp
%include "FeaturesAPI_ExtrusionBoolean.h"
%include "FeaturesAPI_Fillet.h"
%include "FeaturesAPI_Intersection.h"
+%include "FeaturesAPI_Measurement.h"
%include "FeaturesAPI_MultiRotation.h"
%include "FeaturesAPI_MultiTranslation.h"
%include "FeaturesAPI_Partition.h"
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesAPI_Measurement.h"
+
+#include <FeaturesPlugin_Measurement.h>
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelHighAPI_Services.h>
+#include <ModelHighAPI_Tools.h>
+
+double measureLength(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theEdge)
+{
+ FeaturePtr aMeasure = thePart->addFeature(FeaturesPlugin_Measurement::ID());
+ fillAttribute(FeaturesPlugin_Measurement::MEASURE_LENGTH(),
+ aMeasure->string(FeaturesPlugin_Measurement::MEASURE_KIND()));
+ fillAttribute(theEdge, aMeasure->selection(FeaturesPlugin_Measurement::EDGE_FOR_LENGTH_ID()));
+ aMeasure->execute();
+
+ // obtain result
+ AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+ aMeasure->attribute(FeaturesPlugin_Measurement::RESULT_VALUES_ID()));
+ double aValue = aResult->size() ? aResult->value(0) : -1.0;
+
+ // perform removing macro feature Measurement
+ thePart->removeFeature(aMeasure);
+ apply();
+
+ return aValue;
+}
+
+double measureDistance(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theFrom,
+ const ModelHighAPI_Selection& theTo)
+{
+ FeaturePtr aMeasure = thePart->addFeature(FeaturesPlugin_Measurement::ID());
+ fillAttribute(FeaturesPlugin_Measurement::MEASURE_DISTANCE(),
+ aMeasure->string(FeaturesPlugin_Measurement::MEASURE_KIND()));
+ fillAttribute(theFrom,
+ aMeasure->selection(FeaturesPlugin_Measurement::DISTANCE_FROM_OBJECT_ID()));
+ fillAttribute(theTo, aMeasure->selection(FeaturesPlugin_Measurement::DISTANCE_TO_OBJECT_ID()));
+ aMeasure->execute();
+
+ // obtain result
+ AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+ aMeasure->attribute(FeaturesPlugin_Measurement::RESULT_VALUES_ID()));
+ double aValue = aResult->size() ? aResult->value(0) : -1.0;
+
+ // perform removing macro feature Measurement
+ thePart->removeFeature(aMeasure);
+ apply();
+
+ return aValue;
+}
+
+double measureRadius(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theObject)
+{
+ FeaturePtr aMeasure = thePart->addFeature(FeaturesPlugin_Measurement::ID());
+ fillAttribute(FeaturesPlugin_Measurement::MEASURE_RADIUS(),
+ aMeasure->string(FeaturesPlugin_Measurement::MEASURE_KIND()));
+ fillAttribute(theObject, aMeasure->selection(FeaturesPlugin_Measurement::CIRCULAR_OBJECT_ID()));
+ aMeasure->execute();
+
+ // obtain result
+ AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+ aMeasure->attribute(FeaturesPlugin_Measurement::RESULT_VALUES_ID()));
+ double aValue = aResult->size() ? aResult->value(0) : -1.0;
+
+ // perform removing macro feature Measurement
+ thePart->removeFeature(aMeasure);
+ apply();
+
+ return aValue;
+}
+
+std::list<double> measureAngle(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theFrom,
+ const ModelHighAPI_Selection& theTo)
+{
+ FeaturePtr aMeasure = thePart->addFeature(FeaturesPlugin_Measurement::ID());
+ fillAttribute(FeaturesPlugin_Measurement::MEASURE_ANGLE(),
+ aMeasure->string(FeaturesPlugin_Measurement::MEASURE_KIND()));
+ fillAttribute(theFrom, aMeasure->selection(FeaturesPlugin_Measurement::ANGLE_FROM_EDGE_ID()));
+ fillAttribute(theTo, aMeasure->selection(FeaturesPlugin_Measurement::ANGLE_TO_EDGE_ID()));
+ aMeasure->execute();
+
+ // obtain result
+ AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+ aMeasure->attribute(FeaturesPlugin_Measurement::RESULT_VALUES_ID()));
+ std::list<double> aValues;
+ for (int i = 0, n = aResult->size(); i < n; ++i)
+ aValues.push_back(aResult->value(i));
+
+ // perform removing macro feature Measurement
+ thePart->removeFeature(aMeasure);
+ apply();
+
+ return aValues;
+}
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesAPI_Measurement_H_
+#define FeaturesAPI_Measurement_H_
+
+#include "FeaturesAPI.h"
+
+#include <list>
+#include <memory>
+
+class ModelAPI_Document;
+class ModelHighAPI_Selection;
+
+/// \ingroup CPPHighAPI
+/// \brief Calculate length of the edge.
+FEATURESAPI_EXPORT
+double measureLength(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theEdge);
+
+/// \ingroup CPPHighAPI
+/// \brief Calculate distance between objects.
+FEATURESAPI_EXPORT
+double measureDistance(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theFrom,
+ const ModelHighAPI_Selection& theTo);
+
+/// \ingroup CPPHighAPI
+/// \brief Calculate radius of circular.
+FEATURESAPI_EXPORT
+double measureRadius(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theObject);
+
+/// \ingroup CPPHighAPI
+/// \brief Calculate angle(s) between edges.
+FEATURESAPI_EXPORT
+std::list<double> measureAngle(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theFrom,
+ const ModelHighAPI_Selection& theTo);
+
+#endif // FeaturesAPI_Measurement_H_
#include "FeaturesAPI_ExtrusionBoolean.h"
#include "FeaturesAPI_Fillet.h"
#include "FeaturesAPI_Intersection.h"
+ #include "FeaturesAPI_Measurement.h"
#include "FeaturesAPI_MultiRotation.h"
#include "FeaturesAPI_MultiTranslation.h"
#include "FeaturesAPI_Partition.h"
FeaturesPlugin_MultiTranslation.h
FeaturesPlugin_MultiRotation.h
FeaturesPlugin_Fillet.h
+ FeaturesPlugin_Measurement.h
)
SET(PROJECT_SOURCES
FeaturesPlugin_MultiTranslation.cpp
FeaturesPlugin_MultiRotation.cpp
FeaturesPlugin_Fillet.cpp
+ FeaturesPlugin_Measurement.cpp
)
SET(XML_RESOURCES
multitranslation_widget.xml
multirotation_widget.xml
fillet_widget.xml
+ measurement_widget.xml
)
SET(TEXT_RESOURCES
TestUnion4CurvedFaces.py
TestUnion4Faces.py
TestUnionOfUnion.py
+ TestMeasurementLength.py
+ TestMeasurementDistance.py
+ TestMeasurementRadius.py
+ TestMeasurementAngle.py
Test1922.py
Test1942.py
Test1915.py
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesPlugin_Measurement.h"
+
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Session.h>
+
+#include <GeomAPI_Angle.h>
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Face.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Shape.h>
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <iomanip>
+#include <sstream>
+
+FeaturesPlugin_Measurement::FeaturesPlugin_Measurement()
+{
+}
+
+void FeaturesPlugin_Measurement::initAttributes()
+{
+ data()->addAttribute(FeaturesPlugin_Measurement::MEASURE_KIND(),
+ ModelAPI_AttributeString::typeId());
+
+ // attribute for length
+ data()->addAttribute(EDGE_FOR_LENGTH_ID(), ModelAPI_AttributeSelection::typeId());
+ // attributes for distance
+ data()->addAttribute(DISTANCE_FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(DISTANCE_TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ // attribute for radius
+ data()->addAttribute(CIRCULAR_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ // attribute for angle
+ data()->addAttribute(ANGLE_FROM_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(ANGLE_TO_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
+ // attribute for result message and values
+ data()->addAttribute(RESULT_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
+}
+
+void FeaturesPlugin_Measurement::execute()
+{
+}
+
+void FeaturesPlugin_Measurement::attributeChanged(const std::string& theID)
+{
+ if (theID == MEASURE_KIND()) {
+ // clear selected objects
+ selection(EDGE_FOR_LENGTH_ID())->reset();
+ selection(DISTANCE_FROM_OBJECT_ID())->reset();
+ selection(DISTANCE_TO_OBJECT_ID())->reset();
+ selection(CIRCULAR_OBJECT_ID())->reset();
+ selection(ANGLE_FROM_EDGE_ID())->reset();
+ selection(ANGLE_TO_EDGE_ID())->reset();
+ string(RESULT_ID())->setValue("");
+ std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+ attribute(RESULT_VALUES_ID()))->setSize(0);
+ }
+ else if (theID != RESULT_ID()) {
+ std::string aKind = string(MEASURE_KIND())->value();
+ if (aKind == MEASURE_LENGTH())
+ computeLength();
+ else if (aKind == MEASURE_DISTANCE())
+ computeDistance();
+ else if (aKind == MEASURE_RADIUS())
+ computeRadius();
+ else if (aKind == MEASURE_ANGLE())
+ computeAngle();
+ }
+}
+
+void FeaturesPlugin_Measurement::computeLength()
+{
+ AttributeSelectionPtr aSelectedFeature = selection(EDGE_FOR_LENGTH_ID());
+
+ GeomShapePtr aShape;
+ GeomEdgePtr anEdge;
+ if (aSelectedFeature)
+ aShape = aSelectedFeature->value();
+ if (!aShape && aSelectedFeature->context())
+ aShape = aSelectedFeature->context()->shape();
+ if (aShape && aShape->isEdge())
+ anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
+ if (!anEdge)
+ return;
+
+ std::ostringstream anOutput;
+ anOutput << "Length = " << std::setprecision(10) << anEdge->length();
+ string(RESULT_ID())->setValue(anOutput.str());
+
+ AttributeDoubleArrayPtr aValues =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+ aValues->setSize(1);
+ aValues->setValue(0, anEdge->length());
+}
+
+void FeaturesPlugin_Measurement::computeDistance()
+{
+ AttributeSelectionPtr aFirstFeature = selection(DISTANCE_FROM_OBJECT_ID());
+ GeomShapePtr aShape1;
+ if (aFirstFeature)
+ aShape1 = aFirstFeature->value();
+ if (!aShape1 && aFirstFeature->context())
+ aShape1 = aFirstFeature->context()->shape();
+
+ AttributeSelectionPtr aSecondFeature = selection(DISTANCE_TO_OBJECT_ID());
+ GeomShapePtr aShape2;
+ if (aSecondFeature)
+ aShape2 = aSecondFeature->value();
+ if (!aShape2 && aSecondFeature->context())
+ aShape2 = aSecondFeature->context()->shape();
+
+ if (!aShape1 || !aShape2)
+ return;
+
+ double aDistance = GeomAlgoAPI_ShapeTools::minimalDistance(aShape1, aShape2);
+
+ std::ostringstream anOutput;
+ anOutput << "Distance = " << std::setprecision(10) << aDistance;
+ string(RESULT_ID())->setValue(anOutput.str());
+
+ AttributeDoubleArrayPtr aValues =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+ aValues->setSize(1);
+ aValues->setValue(0, aDistance);
+}
+
+void FeaturesPlugin_Measurement::computeRadius()
+{
+ AttributeSelectionPtr aSelectedFeature = selection(CIRCULAR_OBJECT_ID());
+
+ GeomShapePtr aShape;
+ if (aSelectedFeature)
+ aShape = aSelectedFeature->value();
+ if (!aShape && aSelectedFeature->context())
+ aShape = aSelectedFeature->context()->shape();
+
+ double aRadius = -1.0;
+ if (aShape) {
+ if (aShape->isEdge()) {
+ GeomEdgePtr anEdge(new GeomAPI_Edge(aShape));
+ if (anEdge->isCircle()) {
+ aRadius = anEdge->circle()->radius();
+ }
+ } else if (aShape->isFace()) {
+ GeomFacePtr aFace(new GeomAPI_Face(aShape));
+ aRadius = GeomAlgoAPI_ShapeTools::radius(aFace);
+ }
+ }
+
+ if (aRadius < 0.0)
+ return;
+
+ std::ostringstream anOutput;
+ anOutput << "Radius = " << std::setprecision(10) << aRadius;
+ string(RESULT_ID())->setValue(anOutput.str());
+
+ AttributeDoubleArrayPtr aValues =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+ aValues->setSize(1);
+ aValues->setValue(0, aRadius);
+}
+
+void FeaturesPlugin_Measurement::computeAngle()
+{
+ AttributeSelectionPtr aFirstFeature = selection(ANGLE_FROM_EDGE_ID());
+ GeomShapePtr aShape1;
+ GeomEdgePtr anEdge1;
+ if (aFirstFeature)
+ aShape1 = aFirstFeature->value();
+ if (!aShape1 && aFirstFeature->context())
+ aShape1 = aFirstFeature->context()->shape();
+ if (aShape1 && aShape1->isEdge())
+ anEdge1 = GeomEdgePtr(new GeomAPI_Edge(aShape1));
+
+
+ AttributeSelectionPtr aSecondFeature = selection(ANGLE_TO_EDGE_ID());
+ GeomShapePtr aShape2;
+ GeomEdgePtr anEdge2;
+ if (aSecondFeature)
+ aShape2 = aSecondFeature->value();
+ if (!aShape2 && aSecondFeature->context())
+ aShape2 = aSecondFeature->context()->shape();
+ if (aShape2 && aShape2->isEdge())
+ anEdge2 = GeomEdgePtr(new GeomAPI_Edge(aShape2));
+
+ if (!anEdge1 || !anEdge2)
+ return;
+
+ GeomShapePtr anInter = anEdge1->intersect(anEdge2);
+
+ std::ostringstream anOutput;
+ anOutput << std::setprecision(10);
+ std::list<double> aValuesList;
+ if (anInter) {
+ if (anInter->isVertex()) {
+ std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
+ std::shared_ptr<GeomAPI_Angle> anAngle(
+ new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
+ double anAngleValue = anAngle->angleDegree();
+ anOutput << "Angle = " << anAngleValue << std::endl;
+ aValuesList.push_back(anAngleValue);
+ }
+ else {
+ GeomAPI_ShapeIterator anIt(anInter);
+ for (int anIndex = 1; anIt.more(); anIt.next(), ++anIndex) {
+ GeomShapePtr aCurrent = anIt.current();
+ if (!aCurrent->isVertex())
+ continue;
+ std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
+ std::shared_ptr<GeomAPI_Angle> anAngle(
+ new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
+ double anAngleValue = anAngle->angleDegree();
+ anOutput << "Angle" << anIndex << " = " << anAngleValue << std::endl;
+ aValuesList.push_back(anAngleValue);
+ }
+ }
+ }
+
+ string(RESULT_ID())->setValue(anOutput.str());
+
+ AttributeDoubleArrayPtr aValues =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+ aValues->setSize((int)aValuesList.size());
+ int anIndex = 0;
+ for (std::list<double>::iterator anIt = aValuesList.begin(); anIt != aValuesList.end(); ++anIt)
+ aValues->setValue(anIndex++, *anIt);
+}
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesPlugin_Measurement_H_
+#define FeaturesPlugin_Measurement_H_
+
+#include "FeaturesPlugin.h"
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_Measurement
+/// \ingroup Plugins
+/// \brief Feature for calculation metrics.
+///
+/// Supported following metrics:
+/// * length of edge,
+/// * distance between shapes,
+/// * radius of arc or cylindrical faces,
+/// * angle between edges.
+class FeaturesPlugin_Measurement : public ModelAPI_Feature
+{
+public:
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Measurement");
+ return MY_ID;
+ }
+
+ /// \return the kind of a feature.
+ virtual const std::string& getKind()
+ {
+ return ID();
+ }
+
+ /// Attribute name for measurement method.
+ inline static const std::string& MEASURE_KIND()
+ {
+ static const std::string MY_MEASURE_KIND_ID("MeasureKind");
+ return MY_MEASURE_KIND_ID;
+ }
+
+ /// Attribute name for length measure.
+ inline static const std::string& MEASURE_LENGTH()
+ {
+ static const std::string MY_MEASURE_ID("Length");
+ return MY_MEASURE_ID;
+ }
+
+ /// Attribute name for distance measure.
+ inline static const std::string& MEASURE_DISTANCE()
+ {
+ static const std::string MY_MEASURE_ID("Distance");
+ return MY_MEASURE_ID;
+ }
+
+ /// Attribute name for radius measure.
+ inline static const std::string& MEASURE_RADIUS()
+ {
+ static const std::string MY_MEASURE_ID("Radius");
+ return MY_MEASURE_ID;
+ }
+
+ /// Attribute name for angle measure.
+ inline static const std::string& MEASURE_ANGLE()
+ {
+ static const std::string MY_MEASURE_ID("Angle");
+ return MY_MEASURE_ID;
+ }
+
+
+ /// Attribute name of edge selected for length calculation.
+ inline static const std::string& EDGE_FOR_LENGTH_ID()
+ {
+ static const std::string MY_EDGE_FOR_LENGTH_ID("edge_for_length");
+ return MY_EDGE_FOR_LENGTH_ID;
+ }
+
+ /// Attribute name of first shape selected for distance calculation.
+ inline static const std::string& DISTANCE_FROM_OBJECT_ID()
+ {
+ static const std::string MY_DISTANCE_FROM_OBJECT_ID("distance_from");
+ return MY_DISTANCE_FROM_OBJECT_ID;
+ }
+
+ /// Attribute name of second shape selected for distance calculation.
+ inline static const std::string& DISTANCE_TO_OBJECT_ID()
+ {
+ static const std::string MY_DISTANCE_TO_OBJECT_ID("distance_to");
+ return MY_DISTANCE_TO_OBJECT_ID;
+ }
+
+ // Attribute name of edge or face selected to calculate radius.
+ inline static const std::string& CIRCULAR_OBJECT_ID()
+ {
+ static const std::string MY_CIRCULAR_OBJECT_ID("circular");
+ return MY_CIRCULAR_OBJECT_ID;
+ }
+
+ /// Attribute name of first edge selected for angle calculation.
+ inline static const std::string& ANGLE_FROM_EDGE_ID()
+ {
+ static const std::string MY_ANGLE_FROM_EDGE_ID("angle_from");
+ return MY_ANGLE_FROM_EDGE_ID;
+ }
+
+ /// Attribute name of second shape selected for distance calculation.
+ inline static const std::string& ANGLE_TO_EDGE_ID()
+ {
+ static const std::string MY_ANGLE_TO_EDGE_ID("angle_to");
+ return MY_ANGLE_TO_EDGE_ID;
+ }
+
+ /// Attribute name for result.
+ inline static const std::string& RESULT_ID()
+ {
+ static const std::string MY_RESULT_ID("result");
+ return MY_RESULT_ID;
+ }
+
+ /// Attribute name for values of result.
+ inline static const std::string& RESULT_VALUES_ID()
+ {
+ static const std::string MY_RESULT_VALUES_ID("result_values");
+ return MY_RESULT_VALUES_ID;
+ }
+
+ /// Creates a new part document if needed
+ FEATURESPLUGIN_EXPORT virtual void execute();
+
+ /// Request for initialization of data model of the feature: adding all attributes
+ FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ /// \param theID identifier of changed attribute
+ FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true.
+ virtual bool isMacro() const { return true; }
+
+ /// Use plugin manager for features creation
+ FeaturesPlugin_Measurement();
+
+private:
+ /// Compute length of the edge
+ void computeLength();
+ /// Compute minimal distance between pair of shapes
+ void computeDistance();
+ /// Compute radius of circular edge or cylindrical face
+ void computeRadius();
+ /// Compute angle(s) between pair of edges if they are intersected
+ void computeAngle();
+};
+
+#endif
#include <FeaturesPlugin_ExtrusionFuse.h>
#include <FeaturesPlugin_Fillet.h>
#include <FeaturesPlugin_Intersection.h>
+#include <FeaturesPlugin_Measurement.h>
#include <FeaturesPlugin_MultiRotation.h>
#include <FeaturesPlugin_MultiTranslation.h>
#include <FeaturesPlugin_Partition.h>
new FeaturesPlugin_ValidatorConcealedResult);
aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection",
new FeaturesPlugin_ValidatorFilletSelection);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorCircular",
+ new FeaturesPlugin_ValidatorCircular);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new FeaturesPlugin_MultiRotation);
} else if (theFeatureID == FeaturesPlugin_Fillet::ID()) {
return FeaturePtr(new FeaturesPlugin_Fillet);
+ } else if (theFeatureID == FeaturesPlugin_Measurement::ID()) {
+ return FeaturePtr(new FeaturesPlugin_Measurement);
}
// feature of such kind is not found
#include <ModelAPI_Tools.h>
#include <GeomValidators_BodyShapes.h>
+#include <GeomValidators_Face.h>
#include <GeomValidators_FeatureKind.h>
#include <GeomValidators_ShapeType.h>
return theError.empty();
}
+
+bool FeaturesPlugin_ValidatorCircular::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ static std::list<std::string> aEdgeArg(1, "circle");
+ static std::list<std::string> aFaceArg(1, "cylinder");
+
+ Events_InfoMessage aError;
+ bool isValid = GeomValidators_ShapeType().isValid(theAttribute, aEdgeArg, aError);
+ if (!isValid) {
+ isValid = GeomValidators_Face().isValid(theAttribute, aFaceArg, aError);
+ if (!isValid)
+ theError = "The shape neither circle nor cylinder";
+ }
+ return isValid;
+}
Events_InfoMessage& theError) const;
};
+/// \class FeaturesPlugin_ValidatorCircular
+/// \ingroup Validators
+/// \brief Verifies the selected object is circular edge or cylindrical face
+class FeaturesPlugin_ValidatorCircular : public ModelAPI_AttributeValidator
+{
+public:
+ //! \return True if the attribute is valid.
+ //! \param[in] theAttribute the checked attribute.
+ //! \param[in] theArguments arguments of the attribute.
+ //! \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
#endif
--- /dev/null
+## Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamL = model.addParameter(Part_1_doc, "L", "40")
+ParamH = model.addParameter(Part_1_doc, "H", "20")
+Point_2 = model.addPoint(Part_1_doc, 0, 100, 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", "Point_1"), False)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(50, 50, 50)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "R")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1])
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_2.result(), SketchCircle_1.results()[1])
+SketchLine_3 = Sketch_1.addLine(70, 40, 30, 40)
+SketchLine_4 = Sketch_1.addLine(30, 40, 30, 60)
+SketchLine_5 = Sketch_1.addLine(30, 60, 70, 60)
+SketchLine_6 = Sketch_1.addLine(70, 60, 70, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), "L")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_4.result(), "H")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "L/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "H/2")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 10)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+SketchLine_7 = Sketch_2.addLine(119.1454520140253, 130.0744845530344, 10, 0)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_8 = SketchProjection_3.createdFeature()
+SketchConstraintAngle_1 = Sketch_2.setAngle(SketchLine_8.result(), SketchLine_7.result(), 50)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.result())
+SketchConstraintDistanceHorizontal_2 = Sketch_2.setHorizontalDistance(SketchAPI_Line(SketchLine_8).startPoint(), SketchLine_7.endPoint(), 10)
+model.do()
+
+TOLERANCE = 1.e-6
+
+# reference data
+REF_DATA = [("Sketch_1/Edge-SketchLine_3", "Sketch_1/Edge-SketchLine_6", [90]),
+ ("Extrusion_1_1/Generated_Face_5", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1", [45]),
+ ("Sketch_1/Edge-SketchCircle_1_2", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1", [0]),
+ ("Sketch_1/Edge-SketchLine_3", "Sketch_1/Edge-SketchCircle_1_2", []),
+ ("Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1", []),
+ ("Sketch_2/Edge-SketchLine_7", "Extrusion_1_1/To_Face_1&Extrusion_1_1/Generated_Face_4", [130]),
+ ("Sketch_2/Edge-SketchLine_7", "Extrusion_1_1/To_Face_1&Extrusion_1_1/Generated_Face_1", [140]),
+ ("Sketch_2/Edge-SketchLine_7", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1", [85.95645561, 95.19768874])
+ ]
+
+for ref in REF_DATA:
+ angle = model.measureAngle(Part_1_doc, model.selection("EDGE", ref[0]), model.selection("EDGE", ref[1]))
+ assert(angle.size() == len(ref[2]))
+ for a, r in zip(angle, ref[2]):
+ assert(math.fabs(a - r) < TOLERANCE), "Angle {} differs from expected value {}".format(a, r)
+
+# select incorrect data
+angle = model.measureAngle(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_7"))
+assert(angle.size() == 0)
+
+model.end()
--- /dev/null
+## Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamL = model.addParameter(Part_1_doc, "L", "40")
+ParamH = model.addParameter(Part_1_doc, "H", "20")
+Point_2 = model.addPoint(Part_1_doc, 0, 100, 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", "Point_1"), False)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(50, 50, 50)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "R")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1])
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_2.result(), SketchCircle_1.results()[1])
+SketchLine_3 = Sketch_1.addLine(70, 40, 30, 40)
+SketchLine_4 = Sketch_1.addLine(30, 40, 30, 60)
+SketchLine_5 = Sketch_1.addLine(30, 60, 70, 60)
+SketchLine_6 = Sketch_1.addLine(70, 60, 70, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), "L")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_4.result(), "H")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "L/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "H/2")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 10)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("YOZ"))
+SketchArc_1 = Sketch_2.addArc(100, 48.41229182762603, 87.5, 0, 87.5, 96.82458365525073, False)
+SketchArc_2 = Sketch_2.addArc(0, 48.41229182762603, 87.5, 0, 87.5, 96.82458365525073, False)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchArc_1.startPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchArc_1.endPoint())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchArc_1.results()[1], "R")
+SketchConstraintRadius_3 = Sketch_2.setRadius(SketchArc_2.results()[1], "2*R")
+SketchLine_7 = Sketch_2.addLine(0, 48.41229182762603, 100, 48.41229182762603)
+SketchLine_7.setAuxiliary(True)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_2.center(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchArc_1.center(), SketchLine_7.endPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_8 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchArc_1.startPoint(), SketchLine_8.result())
+SketchProjection_4 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_9 = SketchProjection_4.createdFeature()
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.startPoint(), SketchLine_9.result())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchArc_2.results()[1])
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_9.result(), [SketchArc_2.results()[1], SketchArc_1.results()[1]])
+[SketchArc_3, SketchArc_4] = SketchConstraintMirror_1.mirrored()
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), 100, 0)
+model.do()
+
+TOLERANCE = 1.e-6
+
+# reference data
+REF_DATA = [(model.selection("VERTEX", "PartSet/Origin"),
+ model.selection("VERTEX", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1"),
+ 122.4744871),
+ (model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1"),
+ model.selection("VERTEX", "Sketch_2/Vertex-SketchArc_1-SketchLine_7e"),
+ 36.94403089),
+ (model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"),
+ model.selection("EDGE", "Extrusion_1_1/Generated_Face_5"),
+ 0),
+ (model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"),
+ model.selection("EDGE", "Extrusion_2_1/Generated_Face_2&Extrusion_2_1/To_Face_1"),
+ 16.00781059),
+ (model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"),
+ model.selection("FACE", "Extrusion_2_1/Generated_Face_2"),
+ 8.412291828),
+ (model.selection("VERTEX", "Sketch_1/Vertex-SketchCircle_1"),
+ model.selection("FACE", "Plane_1"),
+ 35.35533906),
+ (model.selection("FACE", "Extrusion_2_2/From_Face_1"),
+ model.selection("FACE", "Extrusion_2_2/To_Face_1"),
+ 100),
+ (model.selection("FACE", "Extrusion_1_1/Generated_Face_5"),
+ model.selection("FACE", "Extrusion_2_1/Generated_Face_2"),
+ 0),
+ (model.selection("FACE", "Extrusion_1_1/Generated_Face_5"),
+ model.selection("FACE", "Extrusion_1_1/Generated_Face_2"),
+ 27.63932023),
+ (model.selection("SOLID", "Extrusion_1_1"),
+ model.selection("FACE", "Extrusion_2_1/To_Face_1"),
+ 12.5),
+ (model.selection("SOLID", "Extrusion_1_1"),
+ model.selection("SOLID", "Extrusion_2_1"),
+ 0),
+ (model.selection("SOLID", "Extrusion_1_1"),
+ model.selection("SOLID", "Extrusion_2_2"),
+ 87.5)
+ ]
+
+for ref in REF_DATA:
+ dist = model.measureDistance(Part_1_doc, ref[0], ref[1])
+ assert(math.fabs(dist - ref[2]) < TOLERANCE), "Distance {} differs from expected value {}".format(dist, ref[2])
+
+model.end()
--- /dev/null
+## Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamL = model.addParameter(Part_1_doc, "L", "40")
+ParamH = model.addParameter(Part_1_doc, "H", "20")
+Point_2 = model.addPoint(Part_1_doc, 0, 100, 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", "Point_1"), False)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(50, 50, 50)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "R")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1])
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_2.result(), SketchCircle_1.results()[1])
+SketchLine_3 = Sketch_1.addLine(70, 40, 30, 40)
+SketchLine_4 = Sketch_1.addLine(30, 40, 30, 60)
+SketchLine_5 = Sketch_1.addLine(30, 60, 70, 60)
+SketchLine_6 = Sketch_1.addLine(70, 60, 70, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), "L")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_4.result(), "H")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "L/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "H/2")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 10)
+model.do()
+
+TOLERANCE = 1.e-6
+
+# reference data
+REF_DATA = [("Extrusion_1_1/From_Face_1&Extrusion_1_1/Generated_Face_1", ParamH.value()),
+ ("Extrusion_1_1/From_Face_1&Extrusion_1_1/Generated_Face_4", ParamL.value()),
+ ("Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1", ParamR.value() * 2.0 * math.pi),
+ ("Extrusion_1_1/Generated_Face_5&Extrusion_1_1/To_Face_1", 381.981436664),
+ ("Extrusion_1_1/Generated_Face_5", 60),
+ ("Sketch_1/Edge-SketchLine_3", ParamL.value()),
+ ("Sketch_1/Edge-SketchLine_4", ParamH.value()),
+ ("Sketch_1/Edge-SketchCircle_1_2", ParamR.value() * 2.0 * math.pi)
+ ]
+
+for ref in REF_DATA:
+ length = model.measureLength(Part_1_doc, model.selection("EDGE", ref[0]))
+ assert(math.fabs(length - ref[1]) < TOLERANCE), "Length {} differs from expected value {}".format(length, ref[1])
+
+# select incorrect data
+length = model.measureLength(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_5"))
+assert(length == -1)
+
+model.end()
--- /dev/null
+## Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamL = model.addParameter(Part_1_doc, "L", "40")
+ParamH = model.addParameter(Part_1_doc, "H", "20")
+Point_2 = model.addPoint(Part_1_doc, 0, 100, 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", "Point_1"), False)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(50, 50, 50)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "R")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1])
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_2.result(), SketchCircle_1.results()[1])
+SketchLine_3 = Sketch_1.addLine(70, 40, 30, 40)
+SketchLine_4 = Sketch_1.addLine(30, 40, 30, 60)
+SketchLine_5 = Sketch_1.addLine(30, 60, 70, 60)
+SketchLine_6 = Sketch_1.addLine(70, 60, 70, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), "L")
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_4.result(), "H")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "L/2")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_4.startPoint(), SketchCircle_1.center(), "H/2")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 10)
+model.do()
+
+TOLERANCE = 1.e-6
+
+# reference data
+REF_DATA = [(model.selection("EDGE", "Sketch_1/Edge-SketchCircle_1_2"), ParamR.value()),
+ (model.selection("EDGE", "Extrusion_1_1/Generated_Face_5&Extrusion_1_1/From_Face_1"), ParamR.value()),
+ (model.selection("FACE", "Extrusion_1_1/Generated_Face_5"), ParamR.value())
+ ]
+
+for ref in REF_DATA:
+ radius = model.measureRadius(Part_1_doc, ref[0])
+ assert(math.fabs(radius - ref[1]) < TOLERANCE), "Radius {} differs from expected value {}".format(radius, ref[1])
+
+# select incorrect data
+radius = model.measureRadius(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+assert(radius == -1)
+
+model.end()
--- /dev/null
+<!--
+Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+ <toolbox id="MeasureKind">
+ <box id="Length" title="Edge length" icon="icons/Features/meas_length_32x32.png">
+ <shape_selector id="edge_for_length"
+ icon="icons/Features/edge.png"
+ label="Edge"
+ tooltip="Select an edge"
+ shape_types="edge"
+ default="">
+ <validator id="GeomValidators_ShapeType" parameters="edge"/>
+ </shape_selector>
+ </box>
+ <box id="Distance" title="Distance between objects" icon="icons/Features/meas_distance_32x32.png">
+ <shape_selector id="distance_from"
+ icon=""
+ label="From"
+ tooltip="Select a shape"
+ shape_types="vertex edge wire face shell solid objects"
+ default="">
+ </shape_selector>
+ <shape_selector id="distance_to"
+ icon=""
+ label="To"
+ tooltip="Select a shape"
+ shape_types="vertex edge wire face shell solid objects"
+ default="">
+ </shape_selector>
+ </box>
+ <box id="Radius" title="Radius of circular" icon="icons/Features/meas_radius_32x32.png">
+ <shape_selector id="circular"
+ icon=""
+ label="Object"
+ tooltip="Select an edge or face"
+ shape_types="edge face"
+ default="">
+ <validator id="FeaturesPlugin_ValidatorCircular"/>
+ </shape_selector>
+ </box>
+ <box id="Angle" title="Angle between edges" icon="icons/Features/meas_angle_32x32.png">
+ <shape_selector id="angle_from"
+ icon="icons/Features/edge.png"
+ label="First edge"
+ tooltip="Select an edge"
+ shape_types="edge"
+ default="">
+ <validator id="GeomValidators_ShapeType" parameters="edge"/>
+ </shape_selector>
+ <shape_selector id="angle_to"
+ icon="icons/Features/edge.png"
+ label="Second edge"
+ tooltip="Select an edge"
+ shape_types="edge"
+ default="">
+ <validator id="GeomValidators_ShapeType" parameters="edge"/>
+ </shape_selector>
+ </box>
+ </toolbox>
+ <label id="result"/>
+</source>
<source path="multirotation_widget.xml"/>
</feature>
</group>
+ <group id="Measurement">
+ <feature id="Measurement" title="Measurement" tooltip="Calculate properties of objects" icon="icons/Features/measurement.png">
+ <source path="measurement_widget.xml"/>
+ </feature>
+ </group>
</workbench>
</plugin>
GeomAPI_Ax3.h
GeomAPI_Trsf.h
GeomAPI_Angle2d.h
+ GeomAPI_Angle.h
GeomAPI_Wire.h
GeomAPI_Ellipse.h
GeomAPI_Ellipse2d.h
GeomAPI_IPresentable.cpp
GeomAPI_Trsf.cpp
GeomAPI_Angle2d.cpp
+ GeomAPI_Angle.cpp
GeomAPI_Wire.cpp
GeomAPI_Ellipse.cpp
GeomAPI_Ellipse2d.cpp
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <GeomAPI_Angle.h>
+
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Pnt.h>
+
+#include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
+#include <Geom_Curve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <Precision.hxx>
+#include <TopoDS_Edge.hxx>
+
+/// \struct AngleDirections
+/// \brief Used to store info about angle.
+struct AngleDirections {
+ gp_Vec myDir1;
+ gp_Vec myDir2;
+};
+
+#define MY_ANGLE implPtr<AngleDirections>()
+#define PI 3.1415926535897932
+
+
+GeomAPI_Angle::GeomAPI_Angle(const std::shared_ptr<GeomAPI_Edge>& theEdge1,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge2,
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint)
+{
+ gp_Pnt aPoint = thePoint->impl<gp_Pnt>();
+ const TopoDS_Edge& anEdge1 = theEdge1->impl<TopoDS_Edge>();
+ const TopoDS_Edge& anEdge2 = theEdge2->impl<TopoDS_Edge>();
+
+ double aF1, aL1;
+ Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aF1, aL1);
+ double aF2, aL2;
+ Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aF2, aL2);
+
+ AngleDirections* anAngle = new AngleDirections;
+ gp_Pnt aP;
+
+ GeomAPI_ProjectPointOnCurve aProj1(aPoint, aCurve1);
+ if (aProj1.NbPoints() > 0)
+ aCurve1->D1(aProj1.Parameter(1), aP, anAngle->myDir1);
+
+ GeomAPI_ProjectPointOnCurve aProj2(aPoint, aCurve2);
+ if (aProj2.NbPoints() > 0)
+ aCurve2->D1(aProj2.Parameter(1), aP, anAngle->myDir2);
+
+ setImpl(anAngle);
+}
+
+double GeomAPI_Angle::angleDegree()
+{
+ return angleRadian() * 180.0 / PI;
+}
+
+double GeomAPI_Angle::angleRadian()
+{
+ AngleDirections* anAngle = MY_ANGLE;
+ if (anAngle->myDir1.SquareMagnitude() < Precision::SquareConfusion() ||
+ anAngle->myDir2.SquareMagnitude() < Precision::SquareConfusion())
+ return 0.0;
+
+ gp_Dir aDir1(anAngle->myDir1);
+ gp_Dir aDir2(anAngle->myDir2);
+ double aRes = aDir1.Angle(aDir2);
+ aRes = ElCLib::InPeriod(aRes, 0.0, 2.0 * PI);
+ if (Abs(aRes) < 1.e-12)
+ aRes = 0.0;
+ return aRes;
+}
--- /dev/null
+// Copyright (C) 2018-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAPI_Angle_H_
+#define GeomAPI_Angle_H_
+
+#include <GeomAPI_Interface.h>
+
+class GeomAPI_Edge;
+class GeomAPI_Pnt;
+
+/// \class GeomAPI_Angle
+/// \ingroup DataModel
+/// \brief Build an angle
+class GeomAPI_Angle : public GeomAPI_Interface
+{
+public:
+ /// Creation of an angle defined by two edges in the given intersection point.
+ GEOMAPI_EXPORT
+ GeomAPI_Angle(const std::shared_ptr<GeomAPI_Edge>& theEdge1,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge2,
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint);
+
+ /// Returns value of the angle in degrees
+ GEOMAPI_EXPORT double angleDegree();
+ /// Returns value of the angle in radians
+ GEOMAPI_EXPORT double angleRadian();
+};
+
+#endif
// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
//
-#ifndef GeomAPI_Angle_H_
-#define GeomAPI_Angle_H_
+#ifndef GeomAPI_Angle2d_H_
+#define GeomAPI_Angle2d_H_
#include <GeomAPI_Interface.h>
/// Returns list of intersection points if the edge has intersections with the given plane
/// \param thePlane a plane for intersection
GEOMAPI_EXPORT
- void intersectWithPlane(const std::shared_ptr<GeomAPI_Pln> thePlane, std::list<std::shared_ptr<GeomAPI_Pnt> >& theResult) const;
+ void intersectWithPlane(const std::shared_ptr<GeomAPI_Pln> thePlane,
+ std::list<std::shared_ptr<GeomAPI_Pnt> >& theResult) const;
/// Returns edge length.
GEOMAPI_EXPORT
std::shared_ptr<GeomAPI_Pln> getPlane() const;
};
+//! Pointer on attribute object
+typedef std::shared_ptr<GeomAPI_Face> GeomFacePtr;
+
#endif
#include <Geom2d_Curve.hxx>
#include <BRepLib_CheckCurveOnSurface.hxx>
#include <BRep_Tool.hxx>
+#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z()));
}
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::radius(const std::shared_ptr<GeomAPI_Face>& theCylinder)
+{
+ double aRadius = -1.0;
+ if (theCylinder->isCylindrical()) {
+ const TopoDS_Shape& aShape = theCylinder->impl<TopoDS_Shape>();
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape));
+ Handle(Geom_CylindricalSurface) aCyl = Handle(Geom_CylindricalSurface)::DownCast(aSurf);
+ if (!aCyl.IsNull())
+ aRadius = aCyl->Radius();
+ }
+ return aRadius;
+}
+
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2)
+{
+ const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+ BRepExtrema_DistShapeShape aDist(aShape1, aShape2);
+ aDist.Perform();
+ return aDist.IsDone() ? aDist.Value() : Precision::Infinite();
+}
+
//==================================================================================================
std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
const std::shared_ptr<GeomAPI_Shape> theCompound,
GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Pnt>
centreOfMass(const std::shared_ptr<GeomAPI_Shape> theShape);
+ /// \brief Obtain radius of cylindrical face.
+ /// Return negative value if the face is not a cylinder
+ GEOMALGOAPI_EXPORT static double radius(const std::shared_ptr<GeomAPI_Face>& theCylinder);
+
+ /// \brief Calculate minimal distance between shapes
+ GEOMALGOAPI_EXPORT static double minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2);
+
/// \brief Combines faces with common edges to shells, or solids to compsolids.
/// \param[in] theCompound compound of shapes.
/// \param[in] theType type of combine.
from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
from FeaturesAPI import addRecover
from FeaturesAPI import addFillet
+from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle