SET(SHAPER_INSTALL_TUI_DOC doc CACHE INTERNAL "" FORCE)
ENDIF(${HAVE_SALOME})
+# Sketcher: Change radius of circular edges while dragging a point on the edge
+SET(SKETCHER_CHANGE_RADIUS_WHEN_MOVE FALSE)
+
ADD_SUBDIRECTORY (src/Config)
ADD_SUBDIRECTORY (src/Events)
ADD_SUBDIRECTORY (src/Model)
if(initialize()) {
setByDistanceOnEdge(theEdge, theDistanceValue, theDistancePercent, theReverse);
}
-}
+}*/
//==================================================================================================
ConstructionAPI_Point::ConstructionAPI_Point(const std::shared_ptr<ModelAPI_Feature>& theFeature,
if(initialize()) {
GeomAPI_Shape::ShapeType aType1 = getShapeType(theObject1);
GeomAPI_Shape::ShapeType aType2 = getShapeType(theObject2);
-
+ /*
if(aType1 == GeomAPI_Shape::VERTEX && aType2 == GeomAPI_Shape::FACE) {
// If first object is vertex and second object is face then set by projection.
setByProjection(theObject1, theObject2);
} else if(aType1 == GeomAPI_Shape::EDGE && aType2 == GeomAPI_Shape::EDGE) {
// If both objects are edges then set by lines intersection.
setByLinesIntersection(theObject1, theObject2);
- } else if(aType1 == GeomAPI_Shape::EDGE && aType2 == GeomAPI_Shape::FACE) {
+ } else */if(aType1 == GeomAPI_Shape::EDGE && aType2 == GeomAPI_Shape::FACE) {
// If first object is edge and second object is face then set by line and plane intersection.
setByLineAndPlaneIntersection(theObject1, theObject2);
}
}
-}*/
+}
//==================================================================================================
ConstructionAPI_Point::~ConstructionAPI_Point()
fillAttribute(theX, myx);
fillAttribute(theY, myy);
fillAttribute(theZ, myz);
+ fillAttribute(ConstructionPlugin_Point::CREATION_METHOD_BY_XYZ(), mycreationMethod);
execute(false);
}
fillAttribute(theEdge2, mysecondLine);
execute();
-}
+}*/
//==================================================================================================
void ConstructionAPI_Point::setByLineAndPlaneIntersection(const ModelHighAPI_Selection& theEdge,
const ModelHighAPI_Selection& theFace)
{
- fillAttribute(ConstructionPlugin_Point::CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION(), mycreationMethod);
+ fillAttribute(
+ ConstructionPlugin_Point::CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION(), mycreationMethod);
fillAttribute(theEdge, myintersectionLine);
fillAttribute(theFace, myintersectionPlane);
-
+ fillAttribute("", useOffset()); // not used by default
execute();
-}*/
+}
//==================================================================================================
void ConstructionAPI_Point::dump(ModelHighAPI_Dumper& theDumper) const
{
- // TODO: all types of points
-
FeaturePtr aBase = feature();
const std::string& aDocName = theDumper.name(aBase->document());
-
- AttributeDoublePtr anAttrX = aBase->real(ConstructionPlugin_Point::X());
- AttributeDoublePtr anAttrY = aBase->real(ConstructionPlugin_Point::Y());
- AttributeDoublePtr anAttrZ = aBase->real(ConstructionPlugin_Point::Z());
- theDumper << aBase << " = model.addPoint(" << aDocName << ", "
- << anAttrX << ", " << anAttrY << ", " << anAttrZ << ")" << std::endl;
+ const std::string& aMeth = creationMethod()->value();
+
+ // common part
+ theDumper << aBase << " = model.addPoint(" << aDocName << ", ";
+
+ if (aMeth == "" || // default is XYZ
+ aMeth == ConstructionPlugin_Point::CREATION_METHOD_BY_XYZ()) {
+ theDumper << x() << ", " << y() << ", " << z() << ")" << std::endl;
+ } else if (aMeth == ConstructionPlugin_Point::CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) {
+ theDumper << intersectionLine() << ", " <<intersectionPlane() ;
+ if (!useOffset()->value().empty()) { // call method with defined offset
+ theDumper << ", " << offset() << ", " << reverseOffset();
+ }
+ theDumper << ")" << std::endl;
+ }
}
//==================================================================================================
const bool theDistancePercent,
const bool theReverse)
{
- // TODO(spo): check that thePart is not empty
std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ConstructionAPI_Point::ID());
return PointPtr(new ConstructionAPI_Point(aFeature, theEdge, theDistanceValue, theDistancePercent, theReverse));
-}
+}*/
//==================================================================================================
PointPtr addPoint(const std::shared_ptr<ModelAPI_Document> & thePart,
const ModelHighAPI_Selection& theObject1,
const ModelHighAPI_Selection& theObject2)
{
- // TODO(spo): check that thePart is not empty
std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ConstructionAPI_Point::ID());
return PointPtr(new ConstructionAPI_Point(aFeature, theObject1, theObject2));
-}*/
+}
+
+//==================================================================================================
+PointPtr addPoint(const std::shared_ptr<ModelAPI_Document> & thePart,
+ const ModelHighAPI_Selection& theObject1,
+ const ModelHighAPI_Selection& theObject2,
+ const ModelHighAPI_Double& theDistanceValue,
+ const bool theReverse)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ConstructionAPI_Point::ID());
+ PointPtr anAPI(new ConstructionAPI_Point(aFeature, theObject1, theObject2));
+
+ fillAttribute(ConstructionPlugin_Point::USE_OFFSET(), anAPI->useOffset());
+ fillAttribute(theDistanceValue, anAPI->offset());
+ fillAttribute(theReverse, anAPI->reverseOffset());
+
+ return anAPI;
+}
const ModelHighAPI_Double& theDistanceValue,
const bool theDistancePercent = false,
const bool theReverse = false);
-
- /// Constructor with values.
+ */
+ /// Constructor with values: intersected objects.
CONSTRUCTIONAPI_EXPORT
ConstructionAPI_Point(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const ModelHighAPI_Selection& theObject1,
- const ModelHighAPI_Selection& theObject2);*/
+ const ModelHighAPI_Selection& theObject2);
/// Destructor.
CONSTRUCTIONAPI_EXPORT
virtual ~ConstructionAPI_Point();
- INTERFACE_3(ConstructionPlugin_Point::ID(),
+ INTERFACE_9(ConstructionPlugin_Point::ID(),
x, ConstructionPlugin_Point::X(), ModelAPI_AttributeDouble, /** X attribute */,
y, ConstructionPlugin_Point::Y(), ModelAPI_AttributeDouble, /** Y attribute */,
- z, ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble, /** Z attribute */)
+ z, ConstructionPlugin_Point::Z(), ModelAPI_AttributeDouble, /** Z attribute */,
+ creationMethod, ConstructionPlugin_Point::CREATION_METHOD(),
+ ModelAPI_AttributeString, /** Creation method */,
+ intersectionLine, ConstructionPlugin_Point::INTERSECTION_LINE(),
+ ModelAPI_AttributeSelection, /** Line for intersection */,
+ intersectionPlane, ConstructionPlugin_Point::INTERSECTION_PLANE(),
+ ModelAPI_AttributeSelection, /** Plane for intersection */,
+ useOffset, ConstructionPlugin_Point::USE_OFFSET(),
+ ModelAPI_AttributeString, /** Use offset */,
+ offset, ConstructionPlugin_Point::OFFSET(),
+ ModelAPI_AttributeDouble, /** Offset */,
+ reverseOffset, ConstructionPlugin_Point::REVERSE_OFFSET(),
+ ModelAPI_AttributeBoolean, /** Reverse offset */)
/// Set point values.
CONSTRUCTIONAPI_EXPORT
void setByLinesIntersection(const ModelHighAPI_Selection& theEdge1,
const ModelHighAPI_Selection& theEdge2);
-
+ */
/// Set line and plane for intersections.
CONSTRUCTIONAPI_EXPORT
void setByLineAndPlaneIntersection(const ModelHighAPI_Selection& theEdge,
- const ModelHighAPI_Selection& theFace);*/
+ const ModelHighAPI_Selection& theFace);
/// Dump wrapped feature
CONSTRUCTIONAPI_EXPORT
const ModelHighAPI_Double& theDistanceValue,
const bool theDistancePercent = false,
const bool theReverse = false);
+*/
+/// \ingroup CPPHighAPI
+/// \brief Create Point feature as an intersection of selected plane (or planar face) and edge
+CONSTRUCTIONAPI_EXPORT
+PointPtr addPoint(const std::shared_ptr<ModelAPI_Document> & thePart,
+ const ModelHighAPI_Selection& theObject1,
+ const ModelHighAPI_Selection& theObject2);
/// \ingroup CPPHighAPI
-/// \brief Create Point feature
+/// \brief Create Point feature as an intersection of selected plane (or planar face) and edge
+/// with positive distance from the plane and flag to reverse the offset direction.
CONSTRUCTIONAPI_EXPORT
PointPtr addPoint(const std::shared_ptr<ModelAPI_Document> & thePart,
const ModelHighAPI_Selection& theObject1,
- const ModelHighAPI_Selection& theObject2);*/
+ const ModelHighAPI_Selection& theObject2,
+ const ModelHighAPI_Double& theDistanceValue,
+ const bool theReverse = false);
#endif /* SRC_CONSTRUCTIONAPI_CONSTRUCTIONAPI_POINT_H_ */
ADD_UNIT_TESTS(TestAxisCreation.py
UnitTestAxis.py
- TestPoint.py
+ TestPoint_XYZ.py
+ TestPoint_LineAndPlane.py
TestPointName.py
TestPlane.py)
ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
aFactory->registerValidator("ConstructionPlugin_ValidatorPointLines",
new ConstructionPlugin_ValidatorPointLines());
- aFactory->registerValidator("ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel",
- new ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel());
+ aFactory->registerValidator("ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel",
+ new ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel());
aFactory->registerValidator("ConstructionPlugin_ValidatorPlaneThreePoints",
new ConstructionPlugin_ValidatorPlaneThreePoints());
aFactory->registerValidator("ConstructionPlugin_ValidatorPlaneLinePoint",
#include <ModelAPI_ResultConstruction.h>
#include <GeomAlgoAPI_PointBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Vertex.h>
+#include <GeomAPI_Pln.h>
//==================================================================================================
ConstructionPlugin_Point::ConstructionPlugin_Point()
//==================================================================================================
void ConstructionPlugin_Point::initAttributes()
{
- //data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
-
data()->addAttribute(X(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(Y(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(Z(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+
/*data()->addAttribute(EDGE(), ModelAPI_AttributeSelection::typeId());
data()->addAttribute(DISTANCE_VALUE(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(DISTANCE_PERCENT(), ModelAPI_AttributeBoolean::typeId());
data()->addAttribute(FIRST_LINE(), ModelAPI_AttributeSelection::typeId());
data()->addAttribute(SECOND_LINE(), ModelAPI_AttributeSelection::typeId());
-
+*/
data()->addAttribute(INTERSECTION_LINE(), ModelAPI_AttributeSelection::typeId());
- data()->addAttribute(INTERSECTION_PLANE(), ModelAPI_AttributeSelection::typeId());*/
+ data()->addAttribute(INTERSECTION_PLANE(), ModelAPI_AttributeSelection::typeId());
+
+ data()->addAttribute(USE_OFFSET(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(OFFSET(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(REVERSE_OFFSET(), ModelAPI_AttributeBoolean::typeId());
}
//==================================================================================================
void ConstructionPlugin_Point::execute()
{
- GeomShapePtr aShape = createByXYZ();
-
- /*GeomShapePtr aShape;
+ GeomShapePtr aShape;
- std::string aCreationMethod = string(CREATION_METHOD())->value();
+ // to support compatibility with old documents where aCreationMethod did not exist
+ std::string aCreationMethod =
+ string(CREATION_METHOD()).get() && !string(CREATION_METHOD())->value().empty() ?
+ string(CREATION_METHOD())->value() : CREATION_METHOD_BY_XYZ();
if(aCreationMethod == CREATION_METHOD_BY_XYZ()) {
aShape = createByXYZ();
- } else if(aCreationMethod == CREATION_METHOD_BY_DISTANCE_ON_EDGE()) {
+ }/* else if(aCreationMethod == CREATION_METHOD_BY_DISTANCE_ON_EDGE()) {
aShape = createByDistanceOnEdge();
} else if(aCreationMethod == CREATION_METHOD_BY_PROJECTION()) {
aShape = createByProjection();
} else if(aCreationMethod == CREATION_METHOD_BY_LINES_INTERSECTION()) {
aShape = createByLinesIntersection();
- } else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) {
+ }*/ else if(aCreationMethod == CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()) {
aShape = createByLineAndPlaneIntersection();
- }*/
+ }
if(!aShape.get()) {
+ setError("Error: intersection not found.");
return;
}
return GeomAlgoAPI_PointBuilder::vertexByIntersection(aFirstEdge, aSecondEdge);
}
+*/
//==================================================================================================
std::shared_ptr<GeomAPI_Vertex> ConstructionPlugin_Point::createByLineAndPlaneIntersection()
{
// Get line.
- AttributeSelectionPtr aLineSelection= selection(INTERSECTION_LINE());
+ AttributeSelectionPtr aLineSelection = selection(INTERSECTION_LINE());
GeomShapePtr aLineShape = aLineSelection->value();
if(!aLineShape.get()) {
aLineShape = aLineSelection->context()->shape();
}
std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(aPlaneShape));
- return GeomAlgoAPI_PointBuilder::vertexByIntersection(anEdge, aFace);
-}*/
+ if (!string(USE_OFFSET())->value().empty()) {
+ double anOffset = real(OFFSET())->value();
+ if (boolean(REVERSE_OFFSET())->value())
+ anOffset = -anOffset;
+ if (fabs(anOffset) > 1.e-9) { // move face
+ aFace->translate(aFace->getPlane()->direction(), anOffset);
+ }
+ }
+
+ return GeomAlgoAPI_ShapeTools::intersect(anEdge, aFace);
+}
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
+#include <math.h>
+
class GeomAPI_Vertex;
/// \class ConstructionPlugin_Point
return CONSTRUCTION_POINT_KIND;
}
- /*/// Attribute name for creation method.
+ /// Attribute name for creation method.
inline static const std::string& CREATION_METHOD()
{
static const std::string MY_CREATION_METHOD_ID("creation_method");
static const std::string MY_CREATION_METHOD_ID("by_xyz");
return MY_CREATION_METHOD_ID;
}
-
+ /*
/// Attribute name for creation method.
inline static const std::string& CREATION_METHOD_BY_DISTANCE_ON_EDGE()
{
static const std::string MY_CREATION_METHOD_ID("by_lines_intersection");
return MY_CREATION_METHOD_ID;
}
-
+ */
/// Attribute name for creation method.
inline static const std::string& CREATION_METHOD_BY_LINE_AND_PLANE_INTERSECTION()
{
static const std::string MY_CREATION_METHOD_ID("by_line_and_plane_intersection");
return MY_CREATION_METHOD_ID;
- }*/
+ }
/// Attribute name for X coordinate.
inline static const std::string& X()
static const std::string ATTR_ID("second_line");
return ATTR_ID;
}
+ */
/// Attribute name for selected intersection line.
inline static const std::string& INTERSECTION_LINE()
{
static const std::string ATTR_ID("intersection_plane");
return ATTR_ID;
- }*/
+ }
+
+ /// Attribute name for use offset for the intersection plane.
+ inline static const std::string& USE_OFFSET()
+ {
+ static const std::string ATTR_ID("use_offset");
+ return ATTR_ID;
+ }
+
+ /// Attribute name for offset for the intersection plane.
+ inline static const std::string& OFFSET()
+ {
+ static const std::string ATTR_ID("offset");
+ return ATTR_ID;
+ }
+
+ /// Attribute name for reverse offset for the intersection plane.
+ inline static const std::string& REVERSE_OFFSET()
+ {
+ static const std::string ATTR_ID("reverse_offset");
+ return ATTR_ID;
+ }
/// Creates a new part document if needed.
CONSTRUCTIONPLUGIN_EXPORT virtual void execute();
std::shared_ptr<GeomAPI_Vertex> createByXYZ();
/*std::shared_ptr<GeomAPI_Vertex> createByDistanceOnEdge();
std::shared_ptr<GeomAPI_Vertex> createByProjection();
- std::shared_ptr<GeomAPI_Vertex> createByLinesIntersection();
- std::shared_ptr<GeomAPI_Vertex> createByLineAndPlaneIntersection();*/
+ std::shared_ptr<GeomAPI_Vertex> createByLinesIntersection();*/
+ std::shared_ptr<GeomAPI_Vertex> createByLineAndPlaneIntersection();
};
#include <GeomAPI_Lin.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_Vertex.h>
+#include <GeomAlgoAPI_ShapeTools.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeBoolean.h>
#include <Events_InfoMessage.h>
+static std::shared_ptr<GeomAPI_Edge> getEdge(const GeomShapePtr theShape);
static std::shared_ptr<GeomAPI_Lin> getLin(const GeomShapePtr theShape);
static std::shared_ptr<GeomAPI_Pln> getPln(const GeomShapePtr theShape);
static std::shared_ptr<GeomAPI_Pnt> getPnt(const GeomShapePtr theShape);
}
//==================================================================================================
-bool ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel::isValid(
+bool ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel::isValid(
const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const
std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
AttributeSelectionPtr anAttribute2 = aFeature->selection(theArguments.front());
- std::shared_ptr<GeomAPI_Lin> aLin;
+ std::shared_ptr<GeomAPI_Edge> anEdge;
std::shared_ptr<GeomAPI_Pln> aPln;
GeomShapePtr aShape1 = anAttribute1->value();
aShape2 = aContext2->shape();
}
- aLin = getLin(aShape1);
+ bool isPlaneFirst = false;
+ anEdge = getEdge(aShape1);
aPln = getPln(aShape2);
- if(!aLin.get() || !aPln.get()) {
- aLin = getLin(aShape2);
+ if(!anEdge.get() || !aPln.get()) {
+ anEdge = getEdge(aShape2);
aPln = getPln(aShape1);
+ isPlaneFirst = true;
}
- if(!aLin.get() || !aPln.get()) {
+ if(!anEdge.get() || !aPln.get()) {
theError = "Wrong shape types selected.";
return false;
}
- if(aPln->isParallel(aLin)) {
- theError = "Plane and line are parallel.";
+ std::shared_ptr<GeomAPI_Face> aPlaneFace(new GeomAPI_Face(isPlaneFirst ? aShape1 : aShape2));
+ if(GeomAlgoAPI_ShapeTools::isParallel(anEdge, aPlaneFace)) {
+ theError = "Plane and edge are parallel.";
return false;
}
return true;
}
+std::shared_ptr<GeomAPI_Edge> getEdge(const GeomShapePtr theShape)
+{
+ if(!theShape->isEdge()) {
+ return std::shared_ptr<GeomAPI_Edge>();
+ }
+
+ std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theShape));
+
+ return anEdge;
+}
+
std::shared_ptr<GeomAPI_Lin> getLin(const GeomShapePtr theShape)
{
std::shared_ptr<GeomAPI_Lin> aLin;
Events_InfoMessage& theError) const;
};
-/// \class ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel
+/// \class ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel
/// \ingroup Validators
-/// \brief A validator for selection line and plane for point by intersection.
-class ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel: public ModelAPI_AttributeValidator
+/// \brief A validator for selection edge and plane for point by intersection.
+class ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel: public ModelAPI_AttributeValidator
{
public:
//! \return True if the attribute is valid.
aPointFeatureData.real("x").setValue(0.)
aPointFeatureData.real("y").setValue(0.)
aPointFeatureData.real("z").setValue(0.)
+aPointFeatureData.string("creation_method").setValue("by_xyz")
aPointFeature.execute()
aSession.finishOperation()
aPoint1Result = aPointFeature.firstResult();
aPointFeatureData.real("x").setValue(0.)
aPointFeatureData.real("y").setValue(0.)
aPointFeatureData.real("z").setValue(100.)
+aPointFeatureData.string("creation_method").setValue("by_xyz")
aPointFeature.execute()
aSession.finishOperation()
aPoint2Result = aPointFeature.firstResult();
+++ /dev/null
-## Copyright (C) 2014-2017 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>
-##
-
-"""
-Test case for Construction Point feature. Written on High API.
-"""
-from ModelAPI import *
-from GeomAPI import *
-
-from salome.shaper import model
-
-# Get session
-aSession = ModelAPI_Session.get()
-
-# Create a part
-aDocument = aSession.activeDocument()
-aSession.startOperation()
-model.addPart(aDocument)
-aDocument = aSession.activeDocument()
-aSession.finishOperation()
-
-# Create a point by coordinates
-aSession.startOperation()
-aPoint = model.addPoint(aDocument, 50, 50, 50)
-aSession.finishOperation()
-assert (len(aPoint.results()) > 0)
-
-# # Create a sketch with lines
-# aSession.startOperation()
-# anOrigin = GeomAPI_Pnt(0, 0, 0)
-# aDirX = GeomAPI_Dir(1, 0, 0)
-# aNorm = GeomAPI_Dir(0, 0, 1)
-# aSketch = model.addSketch(aDocument, GeomAPI_Ax3(anOrigin, aDirX, aNorm))
-# aSketchLine1 = aSketch.addLine(0, 0, 100, 100)
-# aSketchLine2 = aSketch.addLine(0, 100, 100, 0)
-# aSession.finishOperation()
-#
-# # Create a point on line
-# aSession.startOperation()
-# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], 25, True, False)
-# aSession.finishOperation()
-# assert (len(aPoint.result()) > 0)
-#
-# # Create plane
-# aSession.startOperation()
-# aPlane = model.addPlane(aDocument, 1, 1, 1, 1)
-# aSession.finishOperation()
-#
-# # Create a point by projection
-# aSession.startOperation()
-# aPoint = model.addPoint(aDocument, aPoint.result()[0], aPlane.result()[0])
-# aSession.finishOperation()
-# assert (len(aPoint.result()) > 0)
-#
-# # Create a point by lines intersection
-# aSession.startOperation()
-# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], aSketchLine2.result()[0])
-# aSession.finishOperation()
-# assert (len(aPoint.result()) > 0)
-#
-# # Create a point by line and plane intersection
-# aSession.startOperation()
-# aPoint = model.addPoint(aDocument, aSketchLine1.result()[0], aPlane.result()[0])
-# aSession.finishOperation()
-# assert (len(aPoint.result()) > 0)
-
-assert(model.checkPythonDump())
aFeatureData.real("x").setValue(0.)
aFeatureData.real("y").setValue(0.)
aFeatureData.real("z").setValue(0.)
+aFeatureData.string("creation_method").setValue("by_xyz")
aFeatureName = aFeature.name()
aFeature.execute()
aSession.finishOperation()
--- /dev/null
+## Copyright (C) 2014-2017 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>
+##
+
+"""
+Test case for Construction Point feature as intersection of line and plane.
+"""
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 60)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+model.do()
+Sketch_2 = model.addSketch(partSet, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_2.addLine(60, 100, 0, 20)
+SketchArc_1 = Sketch_2.addArc(0, 0, -65.89631323066888, 61.2998850129882, -90, 0, False)
+model.do()
+
+# point by sketch face and a line
+Point_1 = model.addPoint(partSet, model.selection("EDGE", "Sketch_2/Edge-SketchLine_1"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"))
+model.do()
+# check the point position
+rightPosition = GeomAPI_Vertex(-15, 0, 0)
+assert(rightPosition.isEqual(Point_1.results()[0].resultSubShapePair()[0].shape()))
+
+# point by sketch face and an arc, intersection outside of the face, offset is defined
+Point_2 = model.addPoint(partSet, model.selection("EDGE", "Sketch_2/Edge-SketchArc_1"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), 10, True)
+# check the point position
+rightPosition = GeomAPI_Vertex(-89.442719099991606, 0, -10)
+assert(rightPosition.isEqual(Point_2.results()[0].resultSubShapePair()[0].shape()))
+
+
+model.end()
+assert(model.checkPythonDump())
--- /dev/null
+## Copyright (C) 2014-2017 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>
+##
+
+"""
+Test case for Construction Point feature by coordinates.
+"""
+from ModelAPI import *
+from GeomAPI import *
+
+from salome.shaper import model
+
+# Get session
+aSession = ModelAPI_Session.get()
+
+# Create a part
+aDocument = aSession.activeDocument()
+aSession.startOperation()
+model.addPart(aDocument)
+aDocument = aSession.activeDocument()
+aSession.finishOperation()
+
+# Create a point by coordinates
+aSession.startOperation()
+aPoint = model.addPoint(aDocument, 50, 50, 50)
+aSession.finishOperation()
+assert (len(aPoint.results()) > 0)
+
+assert(model.checkPythonDump())
-->
<source>
- <doublevalue id="x" label="X " tooltip="X coordinate" default="0"/>
- <doublevalue id="y" label="Y " tooltip="Y coordinate" default="0"/>
- <doublevalue id="z" label="Z " tooltip="Z coordinate" default="0"/>
-
- <!--<toolbox id="creation_method">
+ <toolbox id="creation_method">
<box id="by_xyz"
title="By X, Y, Z"
tooltip="Point at a given distance from the origin."
icon="icons/Construction/z_size.png"
default="0"/>
</box>
+<!--
<box id="by_distance_on_edge"
title="By distance on edge"
tooltip="Point on an edge, at a given distance of one of its end."
<validator id="ConstructionPlugin_ValidatorPointLines" parameters="first_line"/>
</shape_selector>
</box>
+-->
<box id="by_line_and_plane_intersection"
title="By line and plane intersection"
tooltip="Point by intersection of line and plane."
tooltip="Line for intersection."
icon="icons/Construction/edge.png"
shape_types="edge">
- <validator id="GeomValidators_ShapeType" parameters="line"/>
- <validator id="ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel" parameters="intersection_plane"/>
+ <validator id="ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel" parameters="intersection_plane"/>
</shape_selector>
<shape_selector id="intersection_plane"
label="Plane"
icon="icons/Construction/face.png"
shape_types="face">
<validator id="GeomValidators_Face" parameters="plane"/>
- <validator id="ConstructionPlugin_ValidatorPointLineAndPlaneNotParallel" parameters="intersection_line"/>
+ <validator id="ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel" parameters="intersection_line"/>
</shape_selector>
+ <optionalbox id="use_offset" title="Offset from the plane">
+ <doublevalue id="offset" label="Distance " tooltip="Distance from the plane" min="0" default="0"/>
+ <boolvalue id="reverse_offset" label="Reverse" tooltip="Reverse offset value" default="false"/>
+ </optionalbox>
</box>
- </toolbox>-->
+ </toolbox>
</source>
GeomAPI_Trsf.h
GeomAPI_Angle2d.h
GeomAPI_Wire.h
+ GeomAPI_Ellipse.h
+ GeomAPI_Ellipse2d.h
)
SET(PROJECT_SOURCES
GeomAPI_Trsf.cpp
GeomAPI_Angle2d.cpp
GeomAPI_Wire.cpp
+ GeomAPI_Ellipse.cpp
+ GeomAPI_Ellipse2d.cpp
)
SET(PROJECT_LIBRARIES
std::shared_ptr<GeomAPI_Dir> dir() const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Ax2> GeomAx2Ptr;
+
#endif
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Ax3> GeomAx3Ptr;
+
#endif
\ No newline at end of file
{
}
+//=================================================================================================
+GeomAPI_Circ::GeomAPI_Circ(const GeomCurvePtr& theCurve)
+{
+ Handle(Geom_Curve) aCurve = theCurve->impl<Handle(Geom_Curve)>();
+ Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
+ if (aCirc.IsNull())
+ throw Standard_ConstructionError("GeomAPI_Circ: Curve is not a circle");
+ setImpl(new gp_Circ(aCirc->Circ()));
+}
+
//=================================================================================================
const std::shared_ptr<GeomAPI_Pnt> GeomAPI_Circ::center() const
{
#define GeomAPI_Circ_H_
#include <GeomAPI_Interface.h>
+#include <GeomAPI_Curve.h>
#include <memory>
class GeomAPI_Ax2;
{
public:
- /** \brief Constructs a circle of radius Radius, where theAx2 locates the circle and defines its orientation in 3D space such that:\n
+ /** \brief Constructs a circle of radius Radius, where theAx2 locates
+ * the circle and defines its orientation in 3D space such that:\n
* - the center of the circle is the origin of theAx2;\n
* - the origin, "X Direction" and "Y Direction" of theAx2 define the plane of the circle;\n
* - theAx2 is the local coordinate system of the circle.\n
GEOMAPI_EXPORT GeomAPI_Circ(const std::shared_ptr<GeomAPI_Pnt>& theCenter,
const std::shared_ptr<GeomAPI_Dir>& theDir, double theRadius);
+ /// Creation of circle defined by a curve
+ GEOMAPI_EXPORT GeomAPI_Circ(const GeomCurvePtr& theCurve);
+
/// Return center of the circle
GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt> center() const;
double& theParameter) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Circ> GeomCirclePtr;
+
#endif
double myEnd;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Curve> GeomCurvePtr;
+
#endif
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Dir> GeomDirPtr;
+
#endif
#include<GeomAPI_Circ.h>
#include<GeomAPI_Dir.h>
#include<GeomAPI_Lin.h>
+#include<GeomAPI_Ax2.h>
+#include<GeomAPI_Ellipse.h>
#include <BRepAdaptor_Curve.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
+#include <Geom_Ellipse.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <gp_Ax1.hxx>
#include <gp_Pln.hxx>
+#include <gp_Elips.hxx>
#include <GCPnts_AbscissaPoint.hxx>
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.IsNull()) // degenerative edge
+ return false;
if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)))
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.IsNull()) // degenerative edge
+ return false;
if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)))
{
// Check the difference of first and last parameters to be equal to the curve period
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.IsNull()) // degenerative edge
+ return false;
if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle)))
{
// Check the difference of first and last parameters is not equal the curve period
return false;
}
+bool GeomAPI_Edge::isEllipse() const
+{
+ 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.IsNull()) // degenerative edge
+ return false;
+ if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse)))
+ return true;
+ return false;
+}
+
std::shared_ptr<GeomAPI_Pnt> GeomAPI_Edge::firstPoint()
{
const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z()));
}
-std::shared_ptr<GeomAPI_Circ> GeomAPI_Edge::circle()
+std::shared_ptr<GeomAPI_Circ> GeomAPI_Edge::circle() const
{
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) {
+ if (!aCurve.IsNull()) {
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
- if (aCirc) {
+ if (!aCirc.IsNull()) {
gp_Pnt aLoc = aCirc->Location();
std::shared_ptr<GeomAPI_Pnt> aCenter(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
gp_Dir anAxis = aCirc->Axis().Direction();
return std::shared_ptr<GeomAPI_Circ>(); // not circle
}
-std::shared_ptr<GeomAPI_Lin> GeomAPI_Edge::line()
+std::shared_ptr<GeomAPI_Ellipse> GeomAPI_Edge::ellipse() const
+{
+ 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.IsNull()) {
+ Handle(Geom_Ellipse) aElips = Handle(Geom_Ellipse)::DownCast(aCurve);
+ if (!aElips.IsNull()) {
+ gp_Elips aGpElips = aElips->Elips();
+ std::shared_ptr<GeomAPI_Ellipse> aEllipse(new GeomAPI_Ellipse());
+ aEllipse->setImpl(new gp_Elips(aGpElips));
+ return aEllipse;
+ }
+ }
+ return std::shared_ptr<GeomAPI_Ellipse>(); // not elipse
+}
+
+std::shared_ptr<GeomAPI_Lin> GeomAPI_Edge::line() const
{
const TopoDS_Shape& aShape = const_cast<GeomAPI_Edge*>(this)->impl<TopoDS_Shape>();
double aFirst, aLast;
class GeomAPI_Pnt;
class GeomAPI_Circ;
class GeomAPI_Lin;
+class GeomAPI_Ellipse;
/**\class GeomAPI_Edge
* \ingroup DataModel
GEOMAPI_EXPORT
bool isArc() const;
+ /// Verifies that the edge is an arc of circle
+ GEOMAPI_EXPORT
+ bool isEllipse() const;
+
/// Returns the first vertex coordinates of the edge
GEOMAPI_EXPORT
std::shared_ptr<GeomAPI_Pnt> firstPoint();
/// Returns a circle if edge is based on the circle curve
GEOMAPI_EXPORT
- std::shared_ptr<GeomAPI_Circ> circle();
+ std::shared_ptr<GeomAPI_Circ> circle() const;
+
+ /// Returns an ellipse if edge is based on the ellipse curve
+ GEOMAPI_EXPORT
+ std::shared_ptr<GeomAPI_Ellipse> ellipse() const;
/// Returns a line if edge is based on the linear curve
GEOMAPI_EXPORT
- std::shared_ptr<GeomAPI_Lin> line();
+ std::shared_ptr<GeomAPI_Lin> line() const;
/// Returns true if the current edge is geometrically equal to the given edge
GEOMAPI_EXPORT
bool isDegenerated() const;
};
+//! Pointer on attribute object
+typedef std::shared_ptr<GeomAPI_Edge> GeomEdgePtr;
+
#endif
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: GeomAPI_Ellipse.cpp
+// Created: 25 April 2017
+// Author: Vitaly Smetannikov
+
+#include "GeomAPI_Ellipse.h"
+#include "GeomAPI_Ax2.h"
+#include "GeomAPI_Pnt.h"
+
+#include <gp_Elips.hxx>
+
+#define MY_ELIPS implPtr<gp_Elips>()
+
+GeomAPI_Ellipse::GeomAPI_Ellipse(const std::shared_ptr<GeomAPI_Ax2>& theAx2,
+ double theMajorRadius, double theMinorRadius)
+: GeomAPI_Interface(new gp_Elips(theAx2->impl<gp_Ax2>(), theMajorRadius, theMinorRadius))
+{
+}
+
+std::shared_ptr<GeomAPI_Pnt> GeomAPI_Ellipse::center() const
+{
+ const gp_Pnt& aCenter = MY_ELIPS->Location();
+ return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCenter.X(), aCenter.Y(), aCenter.Z()));
+}
+
+GeomPointPtr GeomAPI_Ellipse::firstFocus() const
+{
+ const gp_Pnt& aFirst = MY_ELIPS->Focus1();
+ return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aFirst.X(), aFirst.Y(), aFirst.Z()));
+}
+
+GeomPointPtr GeomAPI_Ellipse::secondFocus() const
+{
+ const gp_Pnt& aSecond = MY_ELIPS->Focus2();
+ return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aSecond.X(), aSecond.Y(), aSecond.Z()));
+}
+
+double GeomAPI_Ellipse::minorRadius() const
+{
+ return MY_ELIPS->MinorRadius();
+}
+
+double GeomAPI_Ellipse::majorRadius() const
+{
+ return MY_ELIPS->MajorRadius();
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: GeomAPI_Ellipse.h
+// Created: 25 April 2017
+// Author: Vitaly Smetannikov
+
+#ifndef GeomAPI_Ellipse_H_
+#define GeomAPI_Ellipse_H_
+
+#include <GeomAPI_Interface.h>
+#include <memory>
+
+class GeomAPI_Pnt;
+class GeomAPI_Ax2;
+
+
+/**\class GeomAPI_Ellipse
+ * \ingroup DataModel
+ * \brief Ellipse in 3D
+ */
+class GeomAPI_Ellipse : public GeomAPI_Interface
+{
+public:
+
+ /// \brief Constructs an epty ellipse
+ GEOMAPI_EXPORT GeomAPI_Ellipse() : GeomAPI_Interface() {}
+
+ /** \brief Constructs an ellipse with major and minor radiuses,
+ * where theAx2 locates the ellipse and defines its orientation in 3D space such that:\n
+ * - the center of the circle is the origin of theAx2;\n
+ * - the origin, "X Direction" and "Y Direction" of theAx2 define the plane of the circle;\n
+ * - theAx2 is the local coordinate system of the circle.\n
+ * Note: It is possible to create a circle where Radius is equal to 0.0. raised if Radius < 0.
+ */
+ GEOMAPI_EXPORT GeomAPI_Ellipse(const std::shared_ptr<GeomAPI_Ax2>& theAx2,
+ double theMajorRadius, double theMinorRadius);
+
+ /// Returns center of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> center() const;
+
+ /// Returns first focus of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> firstFocus() const;
+
+ /// Returns second focus of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> secondFocus() const;
+
+ /// Returns minor radius of the ellipse
+ GEOMAPI_EXPORT double minorRadius() const;
+
+ /// Returns major radius of the ellipse
+ GEOMAPI_EXPORT double majorRadius() const;
+
+};
+
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Ellipse> GeomEllipsePtr;
+
+#endif
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: GeomAPI_Ellipse2d.cpp
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+
+#include <gp_Ax22d.hxx>
+#include <gp_Elips2d.hxx>
+#include <Precision.hxx>
+
+#define MY_ELLIPSE implPtr<gp_Elips2d>()
+
+static gp_Elips2d* newEllipse(const gp_Pnt2d& theCenter,
+ const gp_Dir2d& theXAxis,
+ const double theMajorRadius,
+ const double theMinorRadius)
+{
+ if (theMajorRadius < theMinorRadius - Precision::Confusion()) {
+ return newEllipse(theCenter, gp_Dir2d(-theXAxis.Y(), theXAxis.X()),
+ theMinorRadius, theMajorRadius);
+ }
+
+ gp_Ax22d anAxis(theCenter, theXAxis);
+ return new gp_Elips2d(anAxis, theMajorRadius, theMinorRadius);
+}
+
+static gp_Elips2d* newEllipse(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
+{
+ const gp_Pnt2d& aCenter = theCenter->impl<gp_Pnt2d>();
+ const gp_Pnt2d& anAxisPnt = theAxisPoint->impl<gp_Pnt2d>();
+ const gp_Pnt2d& aPassedPnt = thePassingPoint->impl<gp_Pnt2d>();
+
+ gp_Dir2d aXAxis(anAxisPnt.XY() - aCenter.XY());
+ double aMajorRadius = anAxisPnt.Distance(aCenter);
+
+ gp_XY aPassedDir = aPassedPnt.XY() - aCenter.XY();
+
+ double X = aPassedDir.Dot(aXAxis.XY()) / aMajorRadius;
+ if (Abs(X) > 1.0 - Precision::Confusion())
+ return 0; // ellipse cannot be created for such parameters
+
+ double Y = aPassedDir.CrossMagnitude(aXAxis.XY());
+ double aMinorRadius = Y / Sqrt(1. - X * X);
+
+ return newEllipse(aCenter, aXAxis, aMajorRadius, aMinorRadius);
+}
+
+
+GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir2d>& theXAxis,
+ const double theMajorRadius,
+ const double theMinorRadius)
+ : GeomAPI_Interface(newEllipse(theCenter->impl<gp_Pnt2d>(), theXAxis->impl<gp_Dir2d>(),
+ theMajorRadius, theMinorRadius))
+{
+}
+
+GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
+ : GeomAPI_Interface(newEllipse(theCenter, theAxisPoint, thePassingPoint))
+{
+}
+
+std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::center() const
+{
+ const gp_Pnt2d& aCenter = MY_ELLIPSE->Location();
+ return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y()));
+}
+
+std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::firstFocus() const
+{
+ const gp_Pnt2d& aFirst = MY_ELLIPSE->Focus1();
+ return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aFirst.X(), aFirst.Y()));
+}
+
+std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::secondFocus() const
+{
+ const gp_Pnt2d& aSecond = MY_ELLIPSE->Focus2();
+ return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aSecond.X(), aSecond.Y()));
+}
+
+double GeomAPI_Ellipse2d::minorRadius() const
+{
+ return MY_ELLIPSE->MinorRadius();
+}
+
+double GeomAPI_Ellipse2d::majorRadius() const
+{
+ return MY_ELLIPSE->MajorRadius();
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: GeomAPI_Ellipse2d.h
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#ifndef GeomAPI_Ellipse2d_H_
+#define GeomAPI_Ellipse2d_H_
+
+#include <GeomAPI_Interface.h>
+
+class GeomAPI_Pnt2d;
+class GeomAPI_Dir2d;
+
+/**\class GeomAPI_Ellipse2d
+ * \ingroup DataModel
+ * \brief Ellipse in 2D
+ */
+class GeomAPI_Ellipse2d : public GeomAPI_Interface
+{
+public:
+ /// \brief Constructs ellipse by center, X-axis and given radii
+ GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir2d>& theXAxis,
+ const double theMajorRadius,
+ const double theMinorRadius);
+
+ /// \brief Constructs ellipse by center and two points lying on the ellipse:
+ /// first of them defines an axis of the ellipse
+ /// and another is just placed on the ellipse.
+ GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theAxisPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint);
+
+ /// Returns center of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> center() const;
+
+ /// Returns first focus of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> firstFocus() const;
+
+ /// Returns second focus of the ellipse
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt2d> secondFocus() const;
+
+ /// Returns minor radius of the ellipse
+ GEOMAPI_EXPORT double minorRadius() const;
+
+ /// Returns major radius of the ellipse
+ GEOMAPI_EXPORT double majorRadius() const;
+};
+
+#endif
bool isCoplanar(const std::shared_ptr<GeomAPI_Lin> theLin) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Lin> GeomLinePtr;
+
#endif
aMyPln.Axis().IsParallel(anOtherPln.Axis(), theTolerance));
}
-bool GeomAPI_Pln::isParallel(const std::shared_ptr<GeomAPI_Lin> theLine)
-{
- std::shared_ptr<GeomAPI_XYZ> aLineDir = theLine->direction()->xyz();
- std::shared_ptr<GeomAPI_XYZ> aLineLoc = theLine->location()->xyz();
-
- std::shared_ptr<GeomAPI_XYZ> aNormal = direction()->xyz();
- std::shared_ptr<GeomAPI_XYZ> aLocation = location()->xyz();
-
- double aDot = aNormal->dot(aLineDir);
- return Abs(aDot) < Precision::SquareConfusion();
-}
-
std::shared_ptr<GeomAPI_Pnt>
GeomAPI_Pln::intersect(const std::shared_ptr<GeomAPI_Lin>& theLine) const
{
GEOMAPI_EXPORT
bool isCoincident(const std::shared_ptr<GeomAPI_Pln> thePlane, const double theTolerance = 1.e-7);
- /// Returns true if plane is parallel to theLine.
- GEOMAPI_EXPORT
- bool isParallel(const std::shared_ptr<GeomAPI_Lin> theLine);
-
/// Returns intersection point or empty if no intersections
GEOMAPI_EXPORT
std::shared_ptr<GeomAPI_Pnt> intersect(const std::shared_ptr<GeomAPI_Lin>& theLine) const;
std::shared_ptr<GeomAPI_Lin> intersect(const std::shared_ptr<GeomAPI_Pln> thePlane) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Pln> GeomPlanePtr;
+
#endif
void translate(const std::shared_ptr<GeomAPI_Dir>& theDir, double theDist);
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Pnt> GeomPointPtr;
+
#endif
bool isEqual(const std::shared_ptr<GeomAPI_Pnt2d>& theOther) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Pnt2d> GeomPnt2dPtr;
+
#endif
return false;
}
+
+void GeomAPI_Shape::translate(const std::shared_ptr<GeomAPI_Dir> theDir, const double theOffset)
+{
+ gp_Dir aDir = theDir->impl<gp_Dir>();
+ gp_Vec aTrsfVec(aDir.XYZ() * theOffset);
+ gp_Trsf aTranslation;
+ aTranslation.SetTranslation(aTrsfVec);
+ TopoDS_Shape aResult = MY_SHAPE->Moved(aTranslation);
+ setImpl(new TopoDS_Shape(aResult));
+}
#ifndef GeomAPI_Shape_H_
#define GeomAPI_Shape_H_
+#include "GeomAPI_Dir.h"
+
#include <GeomAPI_Interface.h>
#include <memory>
#include <list>
/// Returns true if min distance between shapes < tolerance.
GEOMAPI_EXPORT
bool isIntersect(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
+ // Translates the shape along the direction for the given offset
+ GEOMAPI_EXPORT
+ void translate(const std::shared_ptr<GeomAPI_Dir> theDir, const double theOffset);
};
//! Pointer on list of shapes
bool isEqual(const std::shared_ptr<GeomAPI_Shape> theVert) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Vertex> GeomVertexPtr;
+
#endif
}
return aRes;
}
+
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::ellipse(
+ const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius)
+{
+ const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
+ const gp_Dir& aNormal = theNormal->impl<gp_Dir>();
+ const gp_Dir& aMajorAxis = theMajorAxis->impl<gp_Dir>();
+
+ gp_Elips anEllipse(gp_Ax2(aCenter, aNormal, aMajorAxis), theMajorRadius, theMinorRadius);
+
+ BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse);
+ std::shared_ptr<GeomAPI_Edge> aRes(new GeomAPI_Edge);
+ TopoDS_Edge anEdge = anEdgeBuilder.Edge();
+ aRes->setImpl(new TopoDS_Shape(anEdge));
+ return aRes;
+}
std::shared_ptr<GeomAPI_Pnt> theStartPoint,
std::shared_ptr<GeomAPI_Pnt> theEndPoint,
std::shared_ptr<GeomAPI_Dir> theNormal);
+
+ /// Creates elliptic edge
+ static std::shared_ptr<GeomAPI_Edge> ellipse(const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius);
};
#endif
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
+#include <BRepClass_FaceClassifier.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Curve.hxx>
#include <BRepLib_CheckCurveOnSurface.hxx>
#include <Geom_Plane.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <GeomLib_Tool.hxx>
+#include <GeomAPI_ExtremaCurveSurface.hxx>
#include <gp_Pln.hxx>
#include <GProp_GProps.hxx>
#include <IntAna_IntConicQuad.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+
#include <BOPAlgo_Builder.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <TopoDS_Edge.hxx>
return anExt.IsParallel() == Standard_True;
}
+//==================================================================================================
+std::shared_ptr<GeomAPI_Vertex> GeomAlgoAPI_ShapeTools::intersect(
+ const std::shared_ptr<GeomAPI_Edge> theEdge, const std::shared_ptr<GeomAPI_Face> theFace)
+{
+ if(!theEdge.get() || !theFace.get()) {
+ return std::shared_ptr<GeomAPI_Vertex>();
+ }
+
+ TopoDS_Edge anEdge = TopoDS::Edge(theEdge->impl<TopoDS_Shape>());
+ double aFirstOnCurve, aLastOnCurve;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirstOnCurve, aLastOnCurve);
+
+ TopoDS_Face aFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
+ Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
+
+ GeomAPI_ExtremaCurveSurface anExt(aCurve, aSurf);
+ // searching for the best point-intersection
+ int aMaxLevel = 0;
+ gp_Pnt aResult;
+ for(int anIntNum = 1; anIntNum <= anExt.NbExtrema(); anIntNum++) {
+ if (anExt.Distance(anIntNum) > Precision::Confusion())
+ continue;
+ Standard_Real aW, aU, aV;
+ anExt.Parameters(anIntNum, aW, aU, aV);
+ gp_Pnt2d aPointOfSurf(aU, aV);
+ // level of the intersection: if it is inside of edge and/or face the level is higher
+ int aIntLevel = aW > aFirstOnCurve && aW < aLastOnCurve ? 2 : 1;
+ BRepClass_FaceClassifier aFClass(aFace, aPointOfSurf, Precision::Confusion());
+ if (aFClass.State() == TopAbs_IN) // "in" is better than "on"
+ aIntLevel += 2;
+ else if (aFClass.State() == TopAbs_ON)
+ aIntLevel += 1;
+ if (aMaxLevel < aIntLevel) {
+ aMaxLevel = anIntNum;
+ anExt.Points(anIntNum, aResult, aResult);
+ }
+ }
+ if (aMaxLevel > 0) { // intersection found
+ return std::shared_ptr<GeomAPI_Vertex>(
+ new GeomAPI_Vertex(aResult.X(), aResult.Y(), aResult.Z()));
+ }
+ return std::shared_ptr<GeomAPI_Vertex>(); // no intersection found
+}
+
//==================================================================================================
void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
const GeomAlgoAPI_ShapeTools::PointToRefsMap& thePointsInfo,
GEOMALGOAPI_EXPORT static bool isParallel(const std::shared_ptr<GeomAPI_Edge> theEdge,
const std::shared_ptr<GeomAPI_Face> theFace);
+ // Computes intersection point between the edge curve and a face surface (only one point, with
+ // preferences to point that belongs to edge and face boundaries.
+ /// \returns null if there is no intersection
+ GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Vertex> intersect(
+ const std::shared_ptr<GeomAPI_Edge> theEdge, const std::shared_ptr<GeomAPI_Face> theFace);
+
typedef std::map<std::shared_ptr<GeomAPI_Pnt>,
std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
std::list<std::shared_ptr<ModelAPI_Object> > > > PointToRefsMap;
aPoint->real("x")->setValue(theX);
aPoint->real("y")->setValue(theY);
aPoint->real("z")->setValue(theZ);
+ aPoint->string("creation_method")->setValue("by_xyz");
aPoint->data()->setName(theName);
// don't show automatically created feature in the features history
aPoint->setInHistory(aPoint, false);
// selection is invalid after recomputation
Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d");
+// identifier of the selection of the center of circle on edge
+Standard_GUID kCIRCLE_CENTER("d0d0e0f1-217a-4b95-8fbb-0c4132f23718");
+// identifier of the selection of the first focus point of ellipse on edge
+Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d");
+// identifier of the selection of the second focus point of ellipse on edge
+Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32");
+
// on this label is stored:
// TNaming_NamedShape - selected shape
// TNaming_Naming - topological selection information (for the body)
} else {
myTmpContext.reset();
myTmpSubShape.reset();
+ myTmpCenterType = NOT_CENTER;
}
const std::shared_ptr<GeomAPI_Shape>& anOldShape = value();
TDF_Label aSelLab = selectionLabel();
aSelLab.ForgetAttribute(kSIMPLE_REF_ID);
aSelLab.ForgetAttribute(kINVALID_SELECTION);
+ aSelLab.ForgetAttribute(kCIRCLE_CENTER);
+ aSelLab.ForgetAttribute(kELLIPSE_CENTER1);
+ aSelLab.ForgetAttribute(kELLIPSE_CENTER2);
bool isDegeneratedEdge = false;
// do not use the degenerated edge as a shape, a null context and shape is used in the case
owner()->data()->sendAttributeUpdated(this);
}
+void Model_AttributeSelection::setValueCenter(
+ const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+ const CenterType theCenterType, const bool theTemporarily)
+{
+ setValue(theContext, theEdge, theTemporarily);
+ if (theTemporarily) {
+ myTmpCenterType = theCenterType;
+ } else { // store in the data structure
+ TDF_Label aSelLab = selectionLabel();
+ switch(theCenterType) {
+ case CIRCLE_CENTER:
+ TDataStd_UAttribute::Set(aSelLab, kCIRCLE_CENTER);
+ break;
+ case ELLIPSE_FIRST_FOCUS:
+ TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER1);
+ break;
+ case ELLIPSE_SECOND_FOCUS:
+ TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER2);
+ break;
+ }
+ owner()->data()->sendAttributeUpdated(this);
+ }
+}
+
+
void Model_AttributeSelection::removeTemporaryValues()
{
if (myTmpContext.get() || myTmpSubShape.get()) {
}
}
+// returns the center of the edge: circular or elliptical
+GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType)
+{
+ if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) {
+ TopoDS_Shape aShape = theEdge->impl<TopoDS_Shape>();
+ if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ double aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ if (!aCurve.IsNull()) {
+ TopoDS_Vertex aVertex;
+ BRep_Builder aBuilder;
+ if (theType == ModelAPI_AttributeSelection::CIRCLE_CENTER) {
+ Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
+ if (!aCirc.IsNull()) {
+ aBuilder.MakeVertex(aVertex, aCirc->Location(), Precision::Confusion());
+ }
+ } else { // ellipse
+ Handle(Geom_Ellipse) anEll = Handle(Geom_Ellipse)::DownCast(aCurve);
+ if (!anEll.IsNull()) {
+ aBuilder.MakeVertex(aVertex,
+ theType == ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS ?
+ anEll->Focus1() : anEll->Focus2(), Precision::Confusion());
+ }
+ }
+ if (!aVertex.IsNull()) {
+ std::shared_ptr<GeomAPI_Vertex> aResult(new GeomAPI_Vertex);
+ aResult->setImpl(new TopoDS_Vertex(aVertex));
+ return aResult;
+ }
+ }
+ }
+ }
+ return theEdge; // no vertex, so, return the initial edge
+}
+
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
{
+ CenterType aType = NOT_CENTER;
+ std::shared_ptr<GeomAPI_Shape> aResult = internalValue(aType);
+ return centerByEdge(aResult, aType);
+}
+
+std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::internalValue(CenterType& theType)
+{
+ theType = NOT_CENTER;
GeomShapePtr aResult;
if (myTmpContext.get() || myTmpSubShape.get()) {
+ theType = myTmpCenterType;
ResultConstructionPtr aResulConstruction =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(myTmpContext);
if(aResulConstruction.get()) {
if (aSelLab.IsAttribute(kINVALID_SELECTION))
return aResult;
+ if (aSelLab.IsAttribute(kCIRCLE_CENTER))
+ theType = CIRCLE_CENTER;
+ else if (aSelLab.IsAttribute(kELLIPSE_CENTER1))
+ theType = ELLIPSE_FIRST_FOCUS;
+ else if (aSelLab.IsAttribute(kELLIPSE_CENTER2))
+ theType = ELLIPSE_SECOND_FOCUS;
+
+
if (myRef.isInitialized()) {
if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
ResultPtr aContext = context();
TopoDS_Shape aSelShape = aSelection->Get();
aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
aResult->setImpl(new TopoDS_Shape(aSelShape));
+ return aResult;
} else { // for simple construction element: just shape of this construction element
std::shared_ptr<Model_ResultConstruction> aConstr =
std::dynamic_pointer_cast<Model_ResultConstruction>(context());
return myRef.myRef->Label().FindChild(1);
}
+/// prefixes of the shape names with centers defined
+static std::map<ModelAPI_AttributeSelection::CenterType, std::string> kCENTERS_PREFIX;
+
+/// returns the map that contains all possible prefixes of the center-names
+static std::map<ModelAPI_AttributeSelection::CenterType, std::string>& centersMap()
+{
+ if (kCENTERS_PREFIX.empty()) { // fill map by initial values
+ kCENTERS_PREFIX[ModelAPI_AttributeSelection::CIRCLE_CENTER] = "__cc";
+ kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS] = "__eff";
+ kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS] = "__esf";
+ }
+ return kCENTERS_PREFIX;
+}
+
std::string Model_AttributeSelection::namingName(const std::string& theDefaultName)
{
std::string aName("");
if(!this->isInitialized())
return !theDefaultName.empty() ? theDefaultName : aName;
- std::shared_ptr<GeomAPI_Shape> aSubSh = value();
+ CenterType aCenterType = NOT_CENTER;
+ std::shared_ptr<GeomAPI_Shape> aSubSh = internalValue(aCenterType);
ResultPtr aCont = context();
if (!aCont.get()) // in case of selection of removed result
return "";
Model_SelectionNaming aSelNaming(selectionLabel());
- return aSelNaming.namingName(
+ std::string aResult = aSelNaming.namingName(
aCont, aSubSh, theDefaultName, owner()->document() != aCont->document());
+ if (aCenterType != NOT_CENTER) {
+ aResult += centersMap()[aCenterType];
+ }
+ return aResult;
+}
+
+// returns the center type and modifies the shape name if this name is center-name
+static ModelAPI_AttributeSelection::CenterType centerTypeByName(std::string& theShapeName)
+{
+ std::map<ModelAPI_AttributeSelection::CenterType, std::string>::iterator aPrefixIter =
+ centersMap().begin();
+ for(; aPrefixIter != centersMap().end(); aPrefixIter++) {
+ std::size_t aFound = theShapeName.find(aPrefixIter->second);
+ if (aFound != std::string::npos &&
+ aFound == theShapeName.size() - aPrefixIter->second.size()) {
+ theShapeName = theShapeName.substr(0, aFound);
+ return aPrefixIter->first;
+ }
+ }
+ return ModelAPI_AttributeSelection::NOT_CENTER;
}
// type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
{
if(theSubShapeName.empty() || theType.empty()) return;
- // check this is Part-name: 2 delimiters in the name
- std::size_t aPartEnd = theSubShapeName.find('/');
- if (aPartEnd != std::string::npos && aPartEnd != theSubShapeName.rfind('/')) {
- std::string aPartName = theSubShapeName.substr(0, aPartEnd);
- ObjectPtr aFound = owner()->document()->objectByName(ModelAPI_ResultPart::group(), aPartName);
- if (aFound.get()) { // found such part, so asking it for the name
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFound);
- std::string aNameInPart = theSubShapeName.substr(aPartEnd + 1);
- int anIndex;
- std::shared_ptr<GeomAPI_Shape> aSelected = aPart->shapeInPart(aNameInPart, theType, anIndex);
- if (aSelected.get()) {
- setValue(aPart, aSelected);
- TDataStd_Integer::Set(selectionLabel(), anIndex);
- return;
+ std::string aSubShapeName = theSubShapeName;
+ CenterType aCenterType = theType[0] == 'v' || theType[0] == 'V' ? // only for vertex-type
+ centerTypeByName(aSubShapeName) : NOT_CENTER;
+ std::string aType = aCenterType == NOT_CENTER ? theType : "EDGE"; // search for edge now
+
+ // first iteration is selection by name without center prefix, second - in case of problem,
+ // try with initial name
+ for(int aUseCenter = 1; aUseCenter >= 0; aUseCenter--) {
+ if (aUseCenter == 0 && aCenterType != NOT_CENTER) {
+ aSubShapeName = theSubShapeName;
+ aCenterType = NOT_CENTER;
+ aType = theType;
+ } else if (aUseCenter != 1) continue;
+
+ // check this is Part-name: 2 delimiters in the name
+ std::size_t aPartEnd = aSubShapeName.find('/');
+ if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) {
+ std::string aPartName = aSubShapeName.substr(0, aPartEnd);
+ ObjectPtr aFound = owner()->document()->objectByName(ModelAPI_ResultPart::group(), aPartName);
+ if (aFound.get()) { // found such part, so asking it for the name
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFound);
+ std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1);
+ int anIndex;
+ std::shared_ptr<GeomAPI_Shape> aSelected = aPart->shapeInPart(aNameInPart, aType, anIndex);
+ if (aSelected.get()) {
+ if (aCenterType != NOT_CENTER) {
+ if (!aSelected->isEdge())
+ continue;
+ std::shared_ptr<GeomAPI_Edge> aSelectedEdge(new GeomAPI_Edge(aSelected));
+ setValueCenter(aPart, aSelectedEdge, aCenterType);
+ } else
+ setValue(aPart, aSelected);
+ TDataStd_Integer::Set(selectionLabel(), anIndex);
+ return;
+ }
}
}
- }
- Model_SelectionNaming aSelNaming(selectionLabel());
- std::shared_ptr<Model_Document> aDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected;
- ResultPtr aCont;
- if (aSelNaming.selectSubShape(theType, theSubShapeName, aDoc, aShapeToBeSelected, aCont)) {
- // try to find the last context to find the up to date shape
- if (aCont->shape().get() && !aCont->shape()->isNull() &&
- aCont->groupName() == ModelAPI_ResultBody::group() && aDoc == owner()->document()) {
- const TopoDS_Shape aConShape = aCont->shape()->impl<TopoDS_Shape>();
- if (!aConShape.IsNull()) {
- Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel());
- if (!aNS.IsNull()) {
- aNS = TNaming_Tool::CurrentNamedShape(aNS);
+ Model_SelectionNaming aSelNaming(selectionLabel());
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected;
+ ResultPtr aCont;
+ if (aSelNaming.selectSubShape(aType, aSubShapeName, aDoc, aShapeToBeSelected, aCont)) {
+ // try to find the last context to find the up to date shape
+ if (aCont->shape().get() && !aCont->shape()->isNull() &&
+ aCont->groupName() == ModelAPI_ResultBody::group() && aDoc == owner()->document()) {
+ const TopoDS_Shape aConShape = aCont->shape()->impl<TopoDS_Shape>();
+ if (!aConShape.IsNull()) {
+ Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel());
if (!aNS.IsNull() && scope().Contains(aNS->Label())) { // scope check is for 2228
- TDF_Label aLab = aNS->Label();
- while(aLab.Depth() != 7 && aLab.Depth() > 5)
- aLab = aLab.Father();
- ObjectPtr anObj = aDoc->objects()->object(aLab);
- if (anObj.get()) {
- ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
- if (aRes)
- aCont = aRes;
+ aNS = TNaming_Tool::CurrentNamedShape(aNS);
+ if (!aNS.IsNull()) {
+ TDF_Label aLab = aNS->Label();
+ while(aLab.Depth() != 7 && aLab.Depth() > 5)
+ aLab = aLab.Father();
+ ObjectPtr anObj = aDoc->objects()->object(aLab);
+ if (anObj.get()) {
+ ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
+ if (aRes)
+ aCont = aRes;
+ }
}
}
}
}
+ if (aCenterType != NOT_CENTER) {
+ if (!aShapeToBeSelected->isEdge())
+ continue;
+ std::shared_ptr<GeomAPI_Edge> aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected));
+ setValueCenter(aCont, aSelectedEdge, aCenterType);
+ } else
+ setValue(aCont, aShapeToBeSelected);
+ return;
}
- setValue(aCont, aShapeToBeSelected);
- return;
}
TDF_Label aSelLab = selectionLabel();
ResultPtr myTmpContext;
/// temporarily storages to avoid keeping in the data structure if not needed
std::shared_ptr<GeomAPI_Shape> myTmpSubShape;
+ /// temporarily storages to avoid keeping in the data structure if not needed
+ CenterType myTmpCenterType;
/// Reference to the partent attribute, if any (to split selection compounds in issue 1799)
Model_AttributeSelectionList* myParent;
public:
const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
const bool theTemporarily = false);
+ /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
+ /// and stores the vertex of the central point (for ellipse the first or the second focus point)
+ MODEL_EXPORT virtual void setValueCenter(
+ const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+ const CenterType theCenterType,
+ const bool theTemporarily = false);
+
/// Reset temporary stored values
virtual void removeTemporaryValues();
/// Objects are created for features automatically
MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel);
+ /// Returns the selected subshape, internal method that works without knowledge
+ /// about special selection of circle and ellipse focuses (for that the public value
+ /// method calls this and makes additional processing).
+ /// Returns theType type of the center, or NOT_CENTER if it is not.
+ std::shared_ptr<GeomAPI_Shape> internalValue(CenterType& theType);
+
+
/// Performs the selection for the body result (TNaming Selection)
/// Performs the selection for the body result (TNaming selection)
SET(PROJECT_LIBRARIES
Config
+ GeomAPI
)
SET(CMAKE_SWIG_FLAGS -threads -Wall)
ADD_DEFINITIONS(-DMODELAPI_EXPORTS)
#include "ModelAPI_Attribute.h"
#include <ModelAPI_Result.h>
+class GeomAPI_Edge;
+
/**\class ModelAPI_AttributeSelection
* \ingroup DataModel
* \brief Attribute that contains reference to the sub-shape of some result, the selected shape.
class ModelAPI_AttributeSelection : public ModelAPI_Attribute
{
public:
+ /// Type of the center of the circular of elliptical edge
+ enum CenterType {
+ NOT_CENTER, ///< this is not a center
+ CIRCLE_CENTER, ///< center of the circle
+ ELLIPSE_FIRST_FOCUS, ///< first focus point of the ellipse
+ ELLIPSE_SECOND_FOCUS, ///< second focus point of the ellipse
+ };
+
/// Defines the result and its selected sub-shape
/// \param theContext object where the sub-shape was selected
/// \param theSubShape selected sub-shape (if null, the whole context is selected)
const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
const bool theTemporarily = false) = 0;
+ /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
+ /// and stores the vertex of the central point (for ellipse the first or the second focus point)
+ virtual void setValueCenter(
+ const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
+ const CenterType theCenterType,
+ const bool theTemporarily = false) = 0;
+
/// Reset temporary stored values
virtual void removeTemporaryValues() = 0;
#include <ModelAPI.h>
#include <ModelAPI_Events.h>
+#include <GeomAPI_Pnt2d.h>
+
+//#define DEBUG_OBJECT_MOVED_MESSAGE
+#ifdef DEBUG_OBJECT_MOVED_MESSAGE
+#include <iostream>
+#endif
+
ModelAPI_ObjectUpdatedMessage::ModelAPI_ObjectUpdatedMessage(const Events_ID theID,
const void* theSender)
: Events_MessageGroup(theID, theSender)
{
return myObjects;
}
+
+
+// ===== ModelAPI_ObjectMovedMessage =====
+ModelAPI_ObjectMovedMessage::ModelAPI_ObjectMovedMessage(const void* theSender)
+ : Events_Message(Events_Loop::eventByName(EVENT_OBJECT_MOVED), theSender)
+{
+}
+
+void ModelAPI_ObjectMovedMessage::setMovedObject(const ObjectPtr& theMovedObject)
+{
+ myMovedObject = theMovedObject;
+ myMovedAttribute = AttributePtr();
+}
+
+void ModelAPI_ObjectMovedMessage::setMovedAttribute(const AttributePtr& theMovedAttribute)
+{
+ myMovedAttribute = theMovedAttribute;
+ myMovedObject = ObjectPtr();
+}
+
+void ModelAPI_ObjectMovedMessage::setOriginalPosition(double theX, double theY)
+{
+ myOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
+#ifdef DEBUG_OBJECT_MOVED_MESSAGE
+ std::cout << "setOriginalPosition: " << myOriginalPosition->x() << ", "
+ << myOriginalPosition->y() << std::endl;
+#endif
+}
+
+void ModelAPI_ObjectMovedMessage::setOriginalPosition(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+{
+ myOriginalPosition = thePoint;
+#ifdef DEBUG_OBJECT_MOVED_MESSAGE
+ std::cout << "setOriginalPosition: " << myOriginalPosition->x() << ", "
+ << myOriginalPosition->y() << std::endl;
+#endif
+}
+
+void ModelAPI_ObjectMovedMessage::setCurrentPosition(double theX, double theY)
+{
+ myCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
+#ifdef DEBUG_OBJECT_MOVED_MESSAGE
+ std::cout << "setCurrentPosition: " << myCurrentPosition->x() << ", " << myCurrentPosition->y()
+ << ", myCurrentPosition - myOriginalPosition: "
+ << myCurrentPosition->x() - myOriginalPosition->x() << ", "
+ << myCurrentPosition->y() - myOriginalPosition->y() << std::endl;
+#endif
+}
+
+void ModelAPI_ObjectMovedMessage::setCurrentPosition(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
+{
+ myCurrentPosition = thePoint;
+#ifdef DEBUG_OBJECT_MOVED_MESSAGE
+ std::cout << "setCurrentPosition: " << myCurrentPosition->x() << ", " << myCurrentPosition->y()
+ << ", myCurrentPosition - myOriginalPosition: "
+ << myCurrentPosition->x() - myOriginalPosition->x() << ", "
+ << myCurrentPosition->y() - myOriginalPosition->y() << std::endl;
+#endif
+}
class ModelAPI_Document;
class ModelAPI_ResultParameter;
+class GeomAPI_Pnt2d;
/// Event ID that feature is created (comes with ModelAPI_ObjectUpdatedMessage)
static const char * EVENT_OBJECT_CREATED = "ObjectCreated";
int myDOF;
};
+/// Message sent when feature or attrubute has been moved.
+/// Stores the moving object/attribute, original and new positions of mouse.
+class ModelAPI_ObjectMovedMessage : public Events_Message
+{
+ ObjectPtr myMovedObject;
+ AttributePtr myMovedAttribute;
+
+ std::shared_ptr<GeomAPI_Pnt2d> myOriginalPosition;
+ std::shared_ptr<GeomAPI_Pnt2d> myCurrentPosition;
+
+public:
+ MODELAPI_EXPORT ModelAPI_ObjectMovedMessage(const void* theSender = 0);
+
+ /// Set object which is being moved (if the message already contains attribute it will be cleared)
+ MODELAPI_EXPORT void setMovedObject(const ObjectPtr& theMovedObject);
+ /// Set attribute which is being moved (if the message already contains object it will be cleared)
+ MODELAPI_EXPORT void setMovedAttribute(const AttributePtr& theMovedAttribute);
+
+ /// Return moved object
+ ObjectPtr movedObject() const
+ { return myMovedObject; }
+ /// Return moved attribute
+ AttributePtr movedAttribute() const
+ { return myMovedAttribute; }
+
+ /// Set original mouse position
+ MODELAPI_EXPORT void setOriginalPosition(double theX, double theY);
+ /// Set original mouse position
+ MODELAPI_EXPORT void setOriginalPosition(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+ /// Return original mouse position
+ const std::shared_ptr<GeomAPI_Pnt2d>& originalPosition() const
+ { return myOriginalPosition; }
+
+ /// Set current mouse position
+ MODELAPI_EXPORT void setCurrentPosition(double theX, double theY);
+ /// Set current mouse position
+ MODELAPI_EXPORT void setCurrentPosition(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+ /// Return current mouse position
+ const std::shared_ptr<GeomAPI_Pnt2d>& currentPosition() const
+ { return myCurrentPosition; }
+};
+
#endif
aFeature.real("x").setValue(1.)
aFeature.real("y").setValue(-1.)
aFeature.real("z").setValue(0.)
+aFeature.string("creation_method").setValue("by_xyz")
aFeatureName = aFeature.name()
# "2" is because Origin is the first point
assert(aFeatureName == "Point_2")
std::shared_ptr<ModelAPI_Attribute> * temp_attribute;
std::shared_ptr<ModelAPI_Object> * temp_object;
std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+ ModelHighAPI_Selection* temp_selection;
int newmem = 0;
if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_attribute, $descriptor(std::shared_ptr<ModelAPI_Attribute> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
if (temp_attribute) {
} else {
$1 = 0;
}
+ } else if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_selection) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
} else {
$1 = 0;
}
#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefAttrList.h>
+#include <ModelAPI_Events.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
#include "ModelHighAPI_Interface.h"
{
return !(myAttribute && myObject);
}
+
+//--------------------------------------------------------------------------------------
+void ModelHighAPI_RefAttr::fillMessage(
+ const std::shared_ptr<ModelAPI_ObjectMovedMessage>& theMessage) const
+{
+ switch (myVariantType) {
+ case VT_ATTRIBUTE: theMessage->setMovedAttribute(myAttribute); return;
+ case VT_OBJECT: theMessage->setMovedObject(myObject); return;
+ }
+}
class ModelAPI_AttributeRefAttr;
class ModelAPI_AttributeRefAttrList;
class ModelAPI_Object;
+class ModelAPI_ObjectMovedMessage;
class ModelHighAPI_Interface;
//--------------------------------------------------------------------------------------
/**\class ModelHighAPI_RefAttr
MODELHIGHAPI_EXPORT
bool isEmpty() const;
+ /// Fill moved message by the attribute or object
+ MODELHIGHAPI_EXPORT
+ void fillMessage(const std::shared_ptr<ModelAPI_ObjectMovedMessage>& theMessage) const;
+
private:
enum VariantType { VT_ATTRIBUTE, VT_OBJECT } myVariantType;
std::shared_ptr<ModelAPI_Attribute> myAttribute;
{
}
-bool ModuleBase_WidgetEditor::editedValue(double& outValue, QString& outText)
+bool ModuleBase_WidgetEditor::editedValue(double theSpinMinValue, double theSpinMaxValue,
+ double& outValue, QString& outText)
{
bool isValueAccepted = false;
aLay->setContentsMargins(2, 2, 2, 2);
ModuleBase_ParamSpinBox* anEditor = new ModuleBase_ParamSpinBox(myEditorDialog);
- anEditor->setMinimum(0);
- anEditor->setMaximum(DBL_MAX);
+ anEditor->setMinimum(theSpinMinValue);
+ anEditor->setMaximum(theSpinMaxValue);
if (outText.isEmpty())
anEditor->setValue(outValue);
else
if (mySpinBox->hasVariable())
aText = mySpinBox->text();
- isValueAccepted = editedValue(aValue, aText);
+ isValueAccepted = editedValue(mySpinBox->minimum(), mySpinBox->maximum(), aValue, aText);
if (isValueAccepted) {
if (aText.isEmpty()) {
if (mySpinBox->hasVariable()) {
private:
/// Show editor
+ /// \param theSpinMinValue a minimal value of popup menu spin box
+ /// \param theSpinMaxValue a maximum value of popup menu spin box
/// \param theOutValue a result value
/// \param theOutText a result text
/// \return true if the editor value is accepted
- bool editedValue(double& theOutValue, QString& theOutText);
+ bool editedValue(double theSpinMinValue, double theSpinMaxValue,
+ double& theOutValue, QString& theOutText);
private:
///< the current widget feature
PartSet_WidgetShapeSelector.h
PartSet_WidgetSketchCreator.h
PartSet_WidgetSketchLabel.h
+ PartSet_CenterPrs.h
+ PartSet_ExternalPointsMgr.h
)
SET(PROJECT_MOC_HEADERS
PartSet_WidgetShapeSelector.h
PartSet_WidgetSketchCreator.h
PartSet_WidgetSketchLabel.h
+ PartSet_ExternalPointsMgr.h
)
SET(PROJECT_SOURCES
PartSet_WidgetShapeSelector.cpp
PartSet_WidgetSketchCreator.cpp
PartSet_WidgetSketchLabel.cpp
+ PartSet_CenterPrs.cpp
+ PartSet_ExternalPointsMgr.cpp
)
SET(PROJECT_RESOURCES
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: PartSet_CenterPrs.cpp
+// Created: 25 April 2017
+// Author: Vitaly SMETANNIKOV
+
+#include "PartSet_CenterPrs.h"
+
+#include <Geom_CartesianPoint.hxx>
+
+
+IMPLEMENT_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point)
+
+PartSet_CenterPrs::PartSet_CenterPrs(const ObjectPtr& theObject,
+ const GeomEdgePtr& theEdge,
+ const gp_Pnt& theCenter,
+ ModelAPI_AttributeSelection::CenterType theType)
+ : AIS_Point(new Geom_CartesianPoint(theCenter)),
+ myObject(theObject),
+ myEdge(theEdge),
+ myCenterType(theType)
+{
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: PartSet_CenterPrs.h
+// Created: 25 April 2017
+// Author: Vitaly SMETANNIKOV
+
+#ifndef PartSet_CenterPrs_H
+#define PartSet_CenterPrs_H
+
+#include <ModelAPI_Object.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <GeomAPI_Edge.h>
+
+#include <AIS_Point.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <gp_Pnt.hxx>
+
+DEFINE_STANDARD_HANDLE(PartSet_CenterPrs, AIS_Point)
+
+/**
+* \ingroup GUI
+* A presentation class for displaying of centers of external curcular objects in a sketch
+*/
+class PartSet_CenterPrs: public AIS_Point
+{
+public:
+ /// Constructor
+ /// \param theObject an object with circular edge
+ /// \param theEdge a circular edge
+ /// \param theCenter a center point of the circular edge
+ /// \param theType a type of the center
+ Standard_EXPORT PartSet_CenterPrs(const ObjectPtr& theObject,
+ const GeomEdgePtr& theEdge,
+ const gp_Pnt& theCenter,
+ ModelAPI_AttributeSelection::CenterType theType);
+
+ /// Returns an Object which contains the circular edge
+ ObjectPtr object() const { return myObject; }
+
+ /// Returns a circular edge shape
+ GeomEdgePtr edge() const { return myEdge; }
+
+ /// Returns type of the center
+ ModelAPI_AttributeSelection::CenterType centerType() const { return myCenterType; }
+
+ DEFINE_STANDARD_RTTIEXT(PartSet_CenterPrs, AIS_Point)
+
+private:
+ ObjectPtr myObject;
+ GeomEdgePtr myEdge;
+ ModelAPI_AttributeSelection::CenterType myCenterType;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: PartSet_ExternalPointsMgr.cpp
+// Created: 26 April 2017
+// Author: Vitaly SMETANNIKOV
+
+#include "PartSet_ExternalPointsMgr.h"
+#include "PartSet_CenterPrs.h"
+#include "PartSet_Tools.h"
+
+#include <ModelAPI_Tools.h>
+
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <XGUI_Tools.h>
+#include <XGUI_Displayer.h>
+#include <XGUI_Workshop.h>
+#include <XGUI_SelectionMgr.h>
+
+PartSet_ExternalPointsMgr::PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop,
+ const CompositeFeaturePtr& theSketch)
+ : QObject(theWorkshop), myWorkshop(theWorkshop), mySketch(theSketch)
+{
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ connect(aDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
+ SLOT(onDisplayObject(ObjectPtr, AISObjectPtr)));
+
+ connect(aDisplayer, SIGNAL(beforeObjectErase(ObjectPtr, AISObjectPtr)),
+ SLOT(onEraseObject(ObjectPtr, AISObjectPtr)));
+
+ updateCenterPresentations();
+}
+
+
+PartSet_ExternalPointsMgr::~PartSet_ExternalPointsMgr()
+{
+ if (myPresentations.isEmpty())
+ return;
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ if (!aWorkshop)
+ return;
+
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ QMapIterator<ObjectPtr, ListOfAIS> aIt(myPresentations);
+ while (aIt.hasNext()) {
+ aIt.next();
+ ListOfAIS aAISList = aIt.value();
+ foreach (AISObjectPtr aAIS, aAISList) {
+ aDisplayer->eraseAIS(aAIS, false);
+ }
+ }
+}
+
+
+//******************************************************
+QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_ExternalPointsMgr::findCircularEdgesInPlane()
+{
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ QObjectPtrList aDispObjects = aDisplayer->displayedObjects();
+
+ std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+ foreach(ObjectPtr aObj, aDispObjects) {
+ if (myPresentations.contains(aObj))
+ continue;
+
+ // Do not process objects of the current sketch
+ if (isSketchObject(aObj))
+ continue;
+
+ ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ if (aResObj.get()) {
+ GeomShapePtr aShape = aResObj->shape();
+ if (aShape.get()) {
+ GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE);
+ for(; aExplorer.more(); aExplorer.next()) {
+ GeomShapePtr aEdgeShape = aExplorer.current();
+ GeomAPI_Edge anEdge(aEdgeShape);
+ if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) &&
+ anEdge.isInPlane(aPlane)) {
+ bool isContains = false;
+ // Check that edge is not already used.
+ // It is possible that the same edge will be taken from different faces
+ foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
+ GeomAPI_Edge aUsedEdge(aPrs->shape());
+ if (aUsedEdge.isEqual(aEdgeShape)) {
+ isContains = true;
+ break;
+ }
+ }
+ if (!isContains) {
+ std::shared_ptr<ModuleBase_ViewerPrs>
+ aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
+ aResult.append(aPrs);
+ }
+ }
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
+
+void PartSet_ExternalPointsMgr::updateCenterPresentations()
+{
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ // Return if there is no plane defined
+ if (!plane().get()) {
+ connect(aWorkshop->selector(), SIGNAL(selectionChanged()),
+ SLOT(onSelectionChanged()));
+ return;
+ }
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> aEdgesPrs = findCircularEdgesInPlane();
+ foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aEdgesPrs) {
+ GeomEdgePtr aEdge(new GeomAPI_Edge(aPrs->shape()));
+ ListOfAIS aList;
+ if (aEdge->isArc() || aEdge->isCircle()) {
+ GeomCirclePtr aCircle = aEdge->circle();
+ GeomPointPtr aCenter = aCircle->center();
+ Handle(PartSet_CenterPrs) aCentPrs =
+ new PartSet_CenterPrs(aPrs->object(), aEdge, aCenter->impl<gp_Pnt>(),
+ ModelAPI_AttributeSelection::CIRCLE_CENTER);
+
+ AISObjectPtr anAIS(new GeomAPI_AISObject());
+ anAIS->setImpl(new Handle(AIS_InteractiveObject)(aCentPrs));
+ aList.append(anAIS);
+ } else if (aEdge->isEllipse()) {
+ GeomEllipsePtr aEllipse = aEdge->ellipse();
+ GeomPointPtr aF1 = aEllipse->firstFocus();
+ GeomPointPtr aF2 = aEllipse->secondFocus();
+ Handle(PartSet_CenterPrs) aF1Prs =
+ new PartSet_CenterPrs(aPrs->object(), aEdge, aF1->impl<gp_Pnt>(),
+ ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS);
+ Handle(PartSet_CenterPrs) aF2Prs =
+ new PartSet_CenterPrs(aPrs->object(), aEdge, aF2->impl<gp_Pnt>(),
+ ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS);
+
+ AISObjectPtr anAIS1(new GeomAPI_AISObject());
+ anAIS1->setImpl(new Handle(AIS_InteractiveObject)(aF1Prs));
+ aList.append(anAIS1);
+
+ AISObjectPtr anAIS2(new GeomAPI_AISObject());
+ anAIS2->setImpl(new Handle(AIS_InteractiveObject)(aF2Prs));
+ aList.append(anAIS2);
+ }
+ if (myPresentations.contains(aPrs->object()))
+ myPresentations[aPrs->object()].append(aList);
+ else
+ myPresentations[aPrs->object()] = aList;
+ foreach(AISObjectPtr anAIS, aList) {
+ aDisplayer->displayAIS(anAIS, false);
+ aDisplayer->activateAIS(anAIS->impl<Handle(AIS_InteractiveObject)>(), TopAbs_VERTEX, false);
+ }
+ }
+}
+
+std::shared_ptr<GeomAPI_Pln> PartSet_ExternalPointsMgr::plane() const
+{
+ return PartSet_Tools::sketchPlane(mySketch);
+}
+
+void PartSet_ExternalPointsMgr::onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS)
+{
+ updateCenterPresentations();
+}
+
+void PartSet_ExternalPointsMgr::onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS)
+{
+ if (myPresentations.contains(theObj)) {
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ ListOfAIS aList = myPresentations[theObj];
+ foreach(AISObjectPtr aAIS, aList) {
+ aDisplayer->eraseAIS(aAIS, false);
+ }
+ myPresentations.remove(theObj);
+ aDisplayer->updateViewer();
+ }
+}
+
+
+bool PartSet_ExternalPointsMgr::isSketchObject(const ObjectPtr& theRes) const
+{
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theRes);
+ if (!aFeature.get())
+ return false;
+ CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
+ return aComp == mySketch;
+}
+
+void PartSet_ExternalPointsMgr::onSelectionChanged()
+{
+ if (plane().get()) {
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ disconnect(aWorkshop->selector(), SIGNAL(selectionChanged()),
+ this, SLOT(onSelectionChanged()));
+ updateCenterPresentations();
+ }
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: PartSet_ExternalPointsMgr.h
+// Created: 26 April 2017
+// Author: Vitaly SMETANNIKOV
+
+#ifndef PartSet_ExternalPointsMgr_H
+#define PartSet_ExternalPointsMgr_H
+
+
+#include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_Result.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_AISObject.h>
+
+#include <QObject>
+#include <QMap>
+
+class ModuleBase_ViewerPrs;
+class ModuleBase_IWorkshop;
+
+
+/**
+* \ingroup Modules
+* A class to manage display of presentations of center points of circular
+* edges outside of a current sketcher
+*/
+class PartSet_ExternalPointsMgr: public QObject
+{
+ Q_OBJECT
+public:
+ PartSet_ExternalPointsMgr(ModuleBase_IWorkshop* theWorkshop,
+ const CompositeFeaturePtr& theSketch);
+
+ virtual ~PartSet_ExternalPointsMgr();
+
+public slots:
+ /**
+ * A slot which processes display of object
+ * \param theObj the displayed object
+ * \param theAIS its presentation
+ */
+ void onDisplayObject(ObjectPtr theObj, AISObjectPtr theAIS);
+
+ /**
+ * A slot which processes erase of object
+ * \param theObj the displayed object
+ * \param theAIS its presentation
+ */
+ void onEraseObject(ObjectPtr theObj, AISObjectPtr theAIS);
+
+ // Called on selection changed
+ void onSelectionChanged();
+
+private:
+ /**
+ * Returns list of presentations which have displayed shapes with circular edges
+ * (circles, arcs) which are in pane of of the given sketch
+ * \param theSketch - the sketch
+ */
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> findCircularEdgesInPlane();
+
+ /// Creates presentations of centers
+ void updateCenterPresentations();
+
+ /// Returns plane of the current sketch
+ GeomPlanePtr plane() const;
+
+ /**
+ * Checks that the given object is an object of the current sketch
+ * \param theRes an object to check
+ * \return True if the given object is a sub-object of the current sketch
+ */
+ bool isSketchObject(const ObjectPtr& theRes) const;
+
+private:
+ /// Workshop
+ ModuleBase_IWorkshop* myWorkshop;
+
+ /// Current sketch
+ CompositeFeaturePtr mySketch;
+
+ /// Type for list of created AIS objects
+ typedef QList<AISObjectPtr> ListOfAIS;
+
+ /// Map of created AIS objects
+ QMap<ObjectPtr, ListOfAIS> myPresentations;
+};
+
+#endif
\ No newline at end of file
aTreeView->setExpanded(myActivePartIndex, false);
XGUI_DataModel* aDataModel = aWorkshop->objectBrowser()->dataModel();
- myActivePartIndex = aDataModel->documentRootIndex(aActiveDoc);
+ myActivePartIndex = aDataModel->documentRootIndex(aActiveDoc, 0);
bool needUpdate = false;
if (myActivePartIndex.isValid()) {
needUpdate = aTreeView->isExpanded(myActivePartIndex);
//aMgr->setActiveDocument(aMgr->moduleDocument());
return;
}
- if (theIndex.column() != 0) // Use only first column
+ if (theIndex.column() != 1) // Use only first column
return;
XGUI_Workshop* aWorkshop = getWorkshop();
#include "PartSet_WidgetSketchLabel.h"
#include "PartSet_WidgetEditor.h"
#include "PartSet_ResultSketchPrs.h"
+#include "PartSet_ExternalPointsMgr.h"
#include <XGUI_ModuleConnector.h>
#include <XGUI_Displayer.h>
: QObject(theModule), myModule(theModule), myIsEditLaunching(false), myIsDragging(false),
myDragDone(false), myIsMouseOverWindow(false),
myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
- myIsPopupMenuActive(false)
+ myIsPopupMenuActive(false), myExternalPointsMgr(0)
{
ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
Point aMousePnt;
get2dPoint(theWnd, theEvent, aMousePnt);
- double dX = aMousePnt.myCurX - myCurrentPoint.myCurX;
- double dY = aMousePnt.myCurY - myCurrentPoint.myCurY;
+
+ std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(
+ new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
+ std::shared_ptr<GeomAPI_Pnt2d> aCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(
+ new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(aAttrId));
if (aPoint.get() != NULL) {
bool isImmutable = aPoint->setImmutable(true);
- aPoint->move(dX, dY);
+
+ std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
+ <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+ aMessage->setMovedAttribute(aPoint);
+ aMessage->setOriginalPosition(anOriginalPosition);
+ aMessage->setCurrentPosition(aCurrentPosition);
+ Events_Loop::loop()->send(aMessage);
+
isModified = true;
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aMoveEvent);
aPoint->setImmutable(isImmutable);
}
}
std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
if (aSketchFeature) {
- aSketchFeature->move(dX, dY);
+ std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
+ <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+ aMessage->setMovedObject(aFeature);
+ aMessage->setOriginalPosition(anOriginalPosition);
+ aMessage->setCurrentPosition(aCurrentPosition);
+ Events_Loop::loop()->send(aMessage);
isModified = true;
- ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, aMoveEvent);
}
}
}
// were changed here
if (isModified) {
aCurrentOperation->onValuesChanged();
+ Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver
}
- Events_Loop::loop()->flush(aMoveEvent); // up all move events - to be processed in the solver
//Events_Loop::loop()->flush(aUpdateEvent); // up update events - to redisplay presentations
// 5. it is necessary to save current selection in order to restore it after the features moving
// plane filter
if (aPln.get())
aConnector->activateModuleSelectionModes();
+
+ myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
}
void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
myIsConstraintsShown[PartSet_Tools::Expressions] = false;
+ if (myExternalPointsMgr) {
+ delete myExternalPointsMgr;
+ myExternalPointsMgr = 0;
+ }
+
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
DataPtr aData = myCurrentSketch->data();
class ModuleBase_Operation;
class XGUI_OperationMgr;
class XGUI_Workshop;
+class PartSet_ExternalPointsMgr;
class AIS_InteractiveObject;
bool myPreviousUpdateViewerEnabled;
QMap<PartSet_Tools::ConstraintVisibleState, bool> myIsConstraintsShown;
+
+ PartSet_ExternalPointsMgr* myExternalPointsMgr;
};
return isAuxiliaryFeature;
}
+
+
+ResultPtr PartSet_Tools::createFixedByExternalCenter(
+ const ObjectPtr& theObject,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge,
+ ModelAPI_AttributeSelection::CenterType theType,
+ const CompositeFeaturePtr& theSketch,
+ bool theTemporary)
+{
+ FeaturePtr aMyFeature = theSketch->addFeature(SketchPlugin_Point::ID());
+
+ if (aMyFeature) {
+ DataPtr aData = aMyFeature->data();
+ AttributeSelectionPtr anAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
+ (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
+
+ ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (anAttr.get() && aRes.get()) {
+ anAttr->setValueCenter(aRes, theEdge, theType, theTemporary);
+ aMyFeature->execute();
+ return aMyFeature->lastResult();
+ }
+ }
+ return ResultPtr();
+}
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeSelection.h>
#include <Events_Message.h>
* \return boolean result
*/
static bool isAuxiliarySketchEntity(const ObjectPtr& theObject);
+
+ static ResultPtr createFixedByExternalCenter(const ObjectPtr& theObject,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge,
+ ModelAPI_AttributeSelection::CenterType theType,
+ const CompositeFeaturePtr& theSketch,
+ bool theTemporary = false);
+
};
#endif
#include <PartSet_Module.h>
#include <PartSet_SketcherReentrantMgr.h>
#include <PartSet_ExternalObjectsMgr.h>
+#include <PartSet_CenterPrs.h>
#include <XGUI_Tools.h>
#include <XGUI_Workshop.h>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRep_Tool.hxx>
+#include <Geom_Point.hxx>
#include <cfloat>
#include <climits>
// myYSpin->hasVariable() ? myYSpin->text().toStdString() : "");
//aPoint->setValue(!myXSpin->hasVariable() ? myXSpin->value() : aPoint->x(),
// !myYSpin->hasVariable() ? myYSpin->value() : aPoint->y());
- aPoint->setValue(myXSpin->value(), myYSpin->value());
- // after movement the solver will call the update event: optimization
- moveObject(myFeature);
+ if (myFeature->isMacro()) {
+ // Moving points of macro-features has been processed directly (without solver)
+ aPoint->setValue(myXSpin->value(), myYSpin->value());
+ moveObject(myFeature);
+ } else {
+ if (!aPoint->isInitialized())
+ aPoint->setValue(0., 0.);
+
+ std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(
+ new ModelAPI_ObjectMovedMessage(this));
+ aMessage->setMovedAttribute(aPoint);
+ aMessage->setOriginalPosition(aPoint->pnt());
+ aMessage->setCurrentPosition(myXSpin->value(), myYSpin->value());
+ Events_Loop::loop()->send(aMessage);
+ }
+
aPoint->setImmutable(isImmutable);
that->blockSignals(isBlocked);
}
}
}
- // End of Bug dependent fragment
+ // The selection could be a center of an external circular object
+ else if (aFirstValue.get() && (!aFirstValue->interactive().IsNull())) {
+ Handle(PartSet_CenterPrs) aAIS =
+ Handle(PartSet_CenterPrs)::DownCast(aFirstValue->interactive());
+ if (!aAIS.IsNull()) {
+ gp_Pnt aPntComp = aAIS->Component()->Pnt();
+ GeomVertexPtr aVertPtr(new GeomAPI_Vertex(aPntComp.X(), aPntComp.Y(), aPntComp.Z()));
+ TopoDS_Shape aShape = aVertPtr->impl<TopoDS_Shape>();
+
+ ResultPtr aFixedObject =
+ PartSet_Tools::findFixedObjectByExternal(aShape, aAIS->object(), mySketch);
+ if (!aFixedObject.get())
+ aFixedObject = PartSet_Tools::createFixedByExternalCenter(aAIS->object(), aAIS->edge(),
+ aAIS->centerType(), mySketch);
+ if (aFixedObject.get())
+ setConstraintToObject(aFixedObject);
+ // fignal updated should be flushed in order to visualize possible created
+ // external objects e.g. selection of trihedron axis when input end arc point
+ updateObject(feature());
+
+ double aX, aY;
+ if (getPoint2d(aView, aShape, aX, aY)) {
+ // do not create a constraint to the point, which already used by the feature
+ // if the feature contains the point, focus is not switched
+ setPoint(aX, aY);
+ }
+ emit vertexSelected(); // it stops the reentrant operation
+ emit focusOutWidget(this);
+ }
+ }
else {
// A case when point is taken from mouse event
gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
#include <GeomDataAPI_Dir.h>
#include <GeomAPI_XYZ.h>
#include <GeomAPI_Face.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <SketchPlugin_Sketch.h>
#include <SketcherPrs_Tools.h>
std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
// X axis is preferable to be dirX on the sketch
const double tol = Precision::Confusion();
- bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol;
+ bool isX = fabs(fabs(anA) - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol;
std::shared_ptr<GeomAPI_Dir> aTempDir(
isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0));
std::shared_ptr<GeomAPI_Dir> aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir)));
aModule->onViewTransformed();
}
}
+
+
+//******************************************************
+QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
+{
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> aResult;
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ QObjectPtrList aDispObjects = aDisplayer->displayedObjects();
+
+ std::shared_ptr<GeomAPI_Pln> aPlane = plane();
+ foreach(ObjectPtr aObj, aDispObjects) {
+ ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ if (aResObj.get()) {
+ GeomShapePtr aShape = aResObj->shape();
+ if (aShape.get()) {
+ GeomAPI_ShapeExplorer aExplorer(aShape, GeomAPI_Shape::EDGE);
+ for(; aExplorer.more(); aExplorer.next()) {
+ GeomShapePtr aEdgeShape = aExplorer.current();
+ GeomAPI_Edge anEdge(aEdgeShape);
+ if ((anEdge.isCircle() || anEdge.isArc() || anEdge.isEllipse()) &&
+ anEdge.isInPlane(aPlane)) {
+ bool isContains = false;
+ // Check that edge is not used.
+ // It is possible that the same edge will be taken from different faces
+ foreach(std::shared_ptr<ModuleBase_ViewerPrs> aPrs, aResult) {
+ GeomAPI_Edge aUsedEdge(aPrs->shape());
+ if (aUsedEdge.isEqual(aEdgeShape)) {
+ isContains = true;
+ break;
+ }
+ }
+ if (!isContains) {
+ std::shared_ptr<ModuleBase_ViewerPrs>
+ aPrs(new ModuleBase_ViewerPrs(aResObj, aEdgeShape));
+ aResult.append(aPrs);
+ }
+ }
+ }
+ }
+ }
+ }
+ return aResult;
+}
/// \param thePlane a plane
std::shared_ptr<GeomAPI_Dir> setSketchPlane(std::shared_ptr<GeomAPI_Pln> thePlane);
+ /**
+ * Returns list of presentations which have displayed shapes with circular edges
+ * (circles, arcs) which are in pane of of the given sketch
+ * \param theSketch - the sketch
+ */
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>> findCircularEdgesInPlane();
+
private:
/// class to show/hide preview planes
PartSet_PreviewPlanes* myPreviewPlanes;
from SketchAPI import addSketch
from tools import *
+from tests import *
--- /dev/null
+## Copyright (C) 2017 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 ModelAPI import *
+from GeomDataAPI import *
+import ModelHighAPI
+import math
+from salome.shaper.model.sketcher import tools
+
+TOLERANCE = 1.e-7
+
+def assertPoint(thePoint, theCoords):
+ """ Verifies coordinates of the point
+ """
+ aPoint = tools.toList(thePoint)
+ assert aPoint[0] == theCoords[0] and aPoint[1] == theCoords[1], "Wrong '{}' point {}, expected {}".format(thePoint.id(), aPoint, theCoords)
+
+
+def assertLine(theLine, theStart, theEnd):
+ """ Verifies coordinates of line extremities
+ """
+ aLine = tools.toSketchFeature(theLine)
+
+ aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+ aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+ if len(theStart):
+ assertPoint(aStartPnt, theStart)
+ if len(theEnd):
+ assertPoint(aEndPnt, theEnd)
+
+
+def assertCircle(theCircle, theCenter, theRadius):
+ """ Verifies attributes of circle
+ """
+ aCircle = tools.toSketchFeature(theCircle)
+
+ aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
+ if len(theCenter):
+ assertPoint(aCenter, theCenter)
+
+ aRadius = aCircle.real("circle_radius")
+ assert aRadius.value() == theRadius, "Wrong circle radius {}, expected {}".format(aRadius.value(), theRadius)
+
+
+def assertArc(theArc, theCenter, theStart, theEnd):
+ """ Verifies coordinates of arc points and the consistency of the arc.
+ Some of points may be empty lists.
+ """
+ anArc = tools.toSketchFeature(theArc)
+
+ aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point"))
+ aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
+ aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point"))
+ if len(theCenter):
+ assertPoint(aCenterPnt, theCenter)
+ if len(theStart):
+ assertPoint(aStartPnt, theStart)
+ if len(theEnd):
+ assertPoint(aEndPnt, theEnd)
+
+ assertArcValidity(anArc)
+
+
+def assertArcValidity(theArc):
+ """ Tests whether the arc is correctly defined
+ """
+ anArc = tools.toSketchFeature(theArc)
+
+ aCenterPnt = geomDataAPI_Point2D(anArc.attribute("center_point"))
+ aStartPnt = geomDataAPI_Point2D(anArc.attribute("start_point"))
+ aEndPnt = geomDataAPI_Point2D(anArc.attribute("end_point"))
+ aRadius = anArc.real("radius")
+ aDistCS = tools.distancePointPoint(aCenterPnt, aStartPnt)
+ aDistCE = tools.distancePointPoint(aCenterPnt, aEndPnt)
+ assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE)
+ assert math.fabs(aRadius.value() - aDistCS) < TOLERANCE, "Wrong arc: radius is {}, expected {}".format(aRadius.value(), aDistCS)
aGeomPnt2 = thePoint2.pnt()
return aGeomPnt1.distance(aGeomPnt2)
+def signedDistancePointLine(thePoint, theLine):
+ aPoint = toList(thePoint)
+ aLine = toSketchFeature(theLine)
+
+ aLineStart = geomDataAPI_Point2D(aLine.attribute("StartPoint")).pnt().xy()
+ aLineEnd = geomDataAPI_Point2D(aLine.attribute("EndPoint")).pnt().xy()
+ aLineDir = aLineEnd.decreased(aLineStart)
+ aLineLen = aLineEnd.distance(aLineStart)
+ aCross = (aPoint[0] - aLineStart.x()) * aLineDir.y() - (aPoint[1] - aLineStart.y()) * aLineDir.x()
+ return aCross / aLineLen
+
+def distancePointLine(thePoint, theLine):
+ return math.fabs(signedDistancePointLine(thePoint, theLine))
+
def lastSubFeature(theSketch, theKind):
"""
obtains last feature of given kind from the sketch
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_ConstraintLength.h>
static const std::string DISTANCE_SETTER("setDistance");
return DISTANCE_SETTER;
}
+ if (theType == SketchPlugin_ConstraintDistanceHorizontal::ID()) {
+ static const std::string DISTANCE_SETTER("setHorizontalDistance");
+ return DISTANCE_SETTER;
+ }
+ if (theType == SketchPlugin_ConstraintDistanceVertical::ID()) {
+ static const std::string DISTANCE_SETTER("setVerticalDistance");
+ return DISTANCE_SETTER;
+ }
if (theType == SketchPlugin_ConstraintEqual::ID()) {
static const std::string EQUAL_SETTER("setEqual");
return EQUAL_SETTER;
if (aValueAttr && aValueAttr->isInitialized())
theDumper << ", " << aValueAttr;
+ if (aBase->getKind() == SketchPlugin_ConstraintDistance::ID()) {
+ AttributeBooleanPtr isSigned = aBase->boolean(SketchPlugin_ConstraintDistance::SIGNED());
+ theDumper << ", " << isSigned->value();
+ }
+
theDumper << ")" << std::endl;
}
execute(true);
}
+void SketchAPI_Projection::setIncludeToResult(bool theKeepResult)
+{
+ fillAttribute(theKeepResult, includeToResult());
+ execute(true);
+}
+
//--------------------------------------------------------------------------------------
std::shared_ptr<SketchAPI_SketchEntity> SketchAPI_Projection::createdFeature() const
{
const std::string& aSketchName = theDumper.parentName(aBase);
AttributeSelectionPtr anExternal = externalFeature();
- theDumper << aBase << " = " << aSketchName << ".addProjection(" << anExternal << ")" << std::endl;
+ AttributeBooleanPtr isIncludeToRes = includeToResult();
+ theDumper << aBase << " = " << aSketchName << ".addProjection("
+ << anExternal << ", " << isIncludeToRes << ")" << std::endl;
// dump "auxiliary" flag if necessary
SketchAPI_SketchEntity::dump(theDumper);
SKETCHAPI_EXPORT
virtual ~SketchAPI_Projection();
- INTERFACE_3(SketchPlugin_Projection::ID(),
+ INTERFACE_4(SketchPlugin_Projection::ID(),
externalFeature, SketchPlugin_Projection::EXTERNAL_FEATURE_ID(),
ModelAPI_AttributeSelection, /** External feature */,
projectedFeature, SketchPlugin_Projection::PROJECTED_FEATURE_ID(),
ModelAPI_AttributeRefAttr, /** Projected feature */,
external, SketchPlugin_Projection::EXTERNAL_ID(),
- ModelAPI_AttributeSelection, /** External */
+ ModelAPI_AttributeSelection, /** External */,
+ includeToResult, SketchPlugin_Projection::INCLUDE_INTO_RESULT(),
+ ModelAPI_AttributeBoolean, /** Include into result */
)
/// Set external feature
SKETCHAPI_EXPORT
void setByExternalName(const std::string & theExternalName);
+ /// Set flag to include projection to result or not
+ SKETCHAPI_EXPORT
+ void setIncludeToResult(bool theKeepResult);
+
/// Returns created feature
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_SketchEntity> createdFeature() const;
}
//--------------------------------------------------------------------------------------
+
+std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Rectangle::lines() const
+{
+ std::list<FeaturePtr> aFeatures;
+ std::list<ObjectPtr> aList = linesList()->list();
+ std::list<ObjectPtr>::const_iterator anIt = aList.begin();
+ for (; anIt != aList.end(); ++anIt)
+ aFeatures.push_back(ModelAPI_Feature::feature(*anIt));
+ return SketchAPI_SketchEntity::wrap(aFeatures);
+}
SKETCHAPI_EXPORT
void setByPoints(const std::shared_ptr<GeomAPI_Pnt2d> & theStartPoint,
const std::shared_ptr<GeomAPI_Pnt2d> & theEndPoint);
+
+ /// List of lines composing rectangle
+ SKETCHAPI_EXPORT std::list<std::shared_ptr<SketchAPI_SketchEntity> > lines() const;
};
//! Pointer on Rectangle object
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_Fillet.h>
#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_ConstraintVertical.h>
#include <SketcherPrs_Tools.h>
//--------------------------------------------------------------------------------------
+#include <ModelAPI_Events.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelHighAPI_Double.h>
#include "SketchAPI_Rotation.h"
#include "SketchAPI_Translation.h"
//--------------------------------------------------------------------------------------
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+#include <cmath>
+//--------------------------------------------------------------------------------------
SketchAPI_Sketch::SketchAPI_Sketch(
const std::shared_ptr<ModelAPI_Feature> & theFeature)
: ModelHighAPI_Interface(theFeature)
//--------------------------------------------------------------------------------------
std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
- const ModelHighAPI_Selection & theExternalFeature)
+ const ModelHighAPI_Selection & theExternalFeature,
+ bool theKeepResult)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_Projection::ID());
- return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalFeature));
+ ProjectionPtr aProjection(new SketchAPI_Projection(aFeature, theExternalFeature));
+ aProjection->setIncludeToResult(theKeepResult);
+ return aProjection;
}
std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
- const std::string & theExternalName)
+ const std::string & theExternalName,
+ bool theKeepResult)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_Projection::ID());
- return ProjectionPtr(new SketchAPI_Projection(aFeature, theExternalName));
+ ProjectionPtr aProjection(new SketchAPI_Projection(aFeature, theExternalName));
+ aProjection->setIncludeToResult(theKeepResult);
+ return aProjection;
}
//--------------------------------------------------------------------------------------
std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setDistance(
const ModelHighAPI_RefAttr & thePoint,
const ModelHighAPI_RefAttr & thePointOrLine,
- const ModelHighAPI_Double & theValue)
+ const ModelHighAPI_Double & theValue,
+ bool isSigned)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_ConstraintDistance::ID());
fillAttribute(thePoint, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
fillAttribute(thePointOrLine, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
+ fillAttribute(isSigned, aFeature->boolean(SketchPlugin_ConstraintDistance::SIGNED()));
+ aFeature->execute();
+ return InterfacePtr(new ModelHighAPI_Interface(aFeature));
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setSignedDistance(
+ const ModelHighAPI_RefAttr & thePoint,
+ const ModelHighAPI_RefAttr & thePointOrLine,
+ const ModelHighAPI_Double & theValue)
+{
+ return setDistance(thePoint, thePointOrLine, theValue, true);
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setUnsignedDistance(
+ const ModelHighAPI_RefAttr & thePoint,
+ const ModelHighAPI_RefAttr & thePointOrLine,
+ const ModelHighAPI_Double & theValue)
+{
+ return setDistance(thePoint, thePointOrLine, theValue, false);
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setHorizontalDistance(
+ const ModelHighAPI_RefAttr & thePoint1,
+ const ModelHighAPI_RefAttr & thePoint2,
+ const ModelHighAPI_Double & theValue)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
+ fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
+ fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
+ fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
+ aFeature->execute();
+ return InterfacePtr(new ModelHighAPI_Interface(aFeature));
+}
+
+std::shared_ptr<ModelHighAPI_Interface> SketchAPI_Sketch::setVerticalDistance(
+ const ModelHighAPI_RefAttr & thePoint1,
+ const ModelHighAPI_RefAttr & thePoint2,
+ const ModelHighAPI_Double & theValue)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
+ fillAttribute(thePoint1, aFeature->refattr(SketchPlugin_Constraint::ENTITY_A()));
+ fillAttribute(thePoint2, aFeature->refattr(SketchPlugin_Constraint::ENTITY_B()));
+ fillAttribute(theValue, aFeature->real(SketchPlugin_Constraint::VALUE()));
aFeature->execute();
return InterfacePtr(new ModelHighAPI_Interface(aFeature));
}
//--------------------------------------------------------------------------------------
+static std::shared_ptr<GeomAPI_Pnt2d> pointCoordinates(const AttributePtr& thePoint)
+{
+ AttributePoint2DPtr aPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint);
+ if (aPnt)
+ return aPnt->pnt();
+ return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnLine(const FeaturePtr& theFeature)
+{
+ AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::START_ID()));
+ AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::END_ID()));
+
+ if (!aStartAttr || !aEndAttr)
+ return std::shared_ptr<GeomAPI_Pnt2d>();
+
+ std::shared_ptr<GeomAPI_XY> aStartPoint = aStartAttr->pnt()->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPoint = aEndAttr->pnt()->xy();
+ return std::shared_ptr<GeomAPI_Pnt2d>(
+ new GeomAPI_Pnt2d(aStartPoint->added(aEndPoint)->multiplied(0.5)));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnCircle(const FeaturePtr& theFeature)
+{
+ AttributePoint2DPtr aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
+ AttributeDoublePtr aRadius = theFeature->real(SketchPlugin_Circle::RADIUS_ID());
+
+ if (!aCenter || !aRadius)
+ return std::shared_ptr<GeomAPI_Pnt2d>();
+
+ return std::shared_ptr<GeomAPI_Pnt2d>(
+ new GeomAPI_Pnt2d(aCenter->x() + aRadius->value(), aCenter->y()));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePointOnArc(const FeaturePtr& theFeature)
+{
+ static const double PI = 3.141592653589793238463;
+
+ AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+ AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::START_ID()));
+ AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::END_ID()));
+
+ if (!aCenterAttr || !aStartAttr || !aEndAttr)
+ return std::shared_ptr<GeomAPI_Pnt2d>();
+
+ std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
+ aStartAttr->x() - aCenterAttr->x(), aStartAttr->y() - aCenterAttr->y()));
+ std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
+ aEndAttr->x() - aCenterAttr->x(), aEndAttr->y() - aCenterAttr->y()));
+
+ double anAngle = aStartDir->angle(aEndDir);
+ bool isReversed = theFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+ if (isReversed && anAngle > 0.)
+ anAngle -= 2.0 * PI;
+ else if (!isReversed && anAngle <= 0.)
+ anAngle += 2.0 * PI;
+
+ double cosA = cos(anAngle);
+ double sinA = sin(anAngle);
+
+ // rotate start dir to find middle point on arc
+ double aRadius = aStartAttr->pnt()->distance(aCenterAttr->pnt());
+ double x = aCenterAttr->x() + aRadius * (aStartDir->x() * cosA - aStartDir->y() * sinA);
+ double y = aCenterAttr->y() + aRadius * (aStartDir->x() * sinA + aStartDir->y() * cosA);
+
+ return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
+}
+
+static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject)
+{
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ if (aFeature) {
+ const std::string& aFeatureKind = aFeature->getKind();
+ if (aFeatureKind == SketchPlugin_Point::ID())
+ return pointCoordinates(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
+ else if (aFeatureKind == SketchPlugin_Line::ID())
+ return middlePointOnLine(aFeature);
+ else if (aFeatureKind == SketchPlugin_Circle::ID())
+ return pointOnCircle(aFeature);
+ else if (aFeatureKind == SketchPlugin_Arc::ID())
+ return middlePointOnArc(aFeature);
+ }
+ // do not move other types of features
+ return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint)
+{
+ std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage(new ModelAPI_ObjectMovedMessage);
+ theMovedEntity.fillMessage(aMessage);
+
+ std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition;
+ if (aMessage->movedAttribute())
+ anOriginalPosition = pointCoordinates(aMessage->movedAttribute());
+ else
+ anOriginalPosition = middlePoint(aMessage->movedObject());
+
+ if (!anOriginalPosition)
+ return; // something has gone wrong, do not process movement
+
+ aMessage->setOriginalPosition(anOriginalPosition);
+ aMessage->setCurrentPosition(theTargetPoint);
+ Events_Loop::loop()->send(aMessage);
+}
+
+void SketchAPI_Sketch::move(const ModelHighAPI_RefAttr& theMovedEntity,
+ double theTargetX, double theTargetY)
+{
+ std::shared_ptr<GeomAPI_Pnt2d> aTargetPoint(new GeomAPI_Pnt2d(theTargetX, theTargetY));
+ move(theMovedEntity, aTargetPoint);
+}
+
+//--------------------------------------------------------------------------------------
+
std::shared_ptr<GeomAPI_Pnt2d> SketchAPI_Sketch::to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
{
FeaturePtr aBase = feature();
/// Add projection
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_Projection> addProjection(
- const ModelHighAPI_Selection & theExternalFeature);
+ const ModelHighAPI_Selection & theExternalFeature,
+ bool theKeepResult = false);
/// Add projection
SKETCHAPI_EXPORT
- std::shared_ptr<SketchAPI_Projection> addProjection(const std::string & theExternalName);
+ std::shared_ptr<SketchAPI_Projection> addProjection(const std::string & theExternalName,
+ bool theKeepResult = false);
/// Add mirror
SKETCHAPI_EXPORT
/// Set distance
SKETCHAPI_EXPORT
std::shared_ptr<ModelHighAPI_Interface> setDistance(
+ const ModelHighAPI_RefAttr & thePoint,
+ const ModelHighAPI_RefAttr & thePointOrLine,
+ const ModelHighAPI_Double & theValue,
+ bool isSigned = false);
+
+ /// Set signed distance
+ SKETCHAPI_EXPORT
+ std::shared_ptr<ModelHighAPI_Interface> setSignedDistance(
+ const ModelHighAPI_RefAttr & thePoint,
+ const ModelHighAPI_RefAttr & thePointOrLine,
+ const ModelHighAPI_Double & theValue);
+
+ /// Set unsigned distance
+ SKETCHAPI_EXPORT
+ std::shared_ptr<ModelHighAPI_Interface> setUnsignedDistance(
const ModelHighAPI_RefAttr & thePoint,
const ModelHighAPI_RefAttr & thePointOrLine,
const ModelHighAPI_Double & theValue);
+ /// Set horizontal distance
+ SKETCHAPI_EXPORT
+ std::shared_ptr<ModelHighAPI_Interface> setHorizontalDistance(
+ const ModelHighAPI_RefAttr & thePoint1,
+ const ModelHighAPI_RefAttr & thePoint2,
+ const ModelHighAPI_Double & theValue);
+
+ /// Set vertical distance
+ SKETCHAPI_EXPORT
+ std::shared_ptr<ModelHighAPI_Interface> setVerticalDistance(
+ const ModelHighAPI_RefAttr & thePoint1,
+ const ModelHighAPI_RefAttr & thePoint2,
+ const ModelHighAPI_Double & theValue);
+
/// Set equal
SKETCHAPI_EXPORT
std::shared_ptr<ModelHighAPI_Interface> setEqual(
const std::shared_ptr<ModelHighAPI_Interface> & theConstraint,
const ModelHighAPI_Double & theValue);
+ /// Move point or sketch feature
+ SKETCHAPI_EXPORT
+ void move(const ModelHighAPI_RefAttr& theMovedEntity,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTargetPoint);
+
+ /// Move point or sketch feature
+ SKETCHAPI_EXPORT
+ void move(const ModelHighAPI_RefAttr& theMovedEntity,
+ double theTargetX, double theTargetY);
+
SKETCHAPI_EXPORT
std::shared_ptr<GeomAPI_Pnt2d> to2D(const std::shared_ptr<GeomAPI_Pnt>& thePoint);
SketchPlugin_ConstraintCoincidence.h
SketchPlugin_ConstraintCollinear.h
SketchPlugin_ConstraintDistance.h
+ SketchPlugin_ConstraintDistanceHorizontal.h
+ SketchPlugin_ConstraintDistanceVertical.h
SketchPlugin_ConstraintEqual.h
SketchPlugin_Fillet.h
SketchPlugin_ConstraintHorizontal.h
SketchPlugin_ConstraintRigid.h
SketchPlugin_ConstraintTangent.h
SketchPlugin_ConstraintVertical.h
+ SketchPlugin_Ellipse.h
SketchPlugin_ExternalValidator.h
SketchPlugin_Feature.h
SketchPlugin_IntersectionPoint.h
SketchPlugin_MacroArc.h
SketchPlugin_MacroArcReentrantMessage.h
SketchPlugin_MacroCircle.h
+ SketchPlugin_MacroEllipse.h
SketchPlugin_MultiRotation.h
SketchPlugin_MultiTranslation.h
SketchPlugin_Plugin.h
SketchPlugin_ConstraintCoincidence.cpp
SketchPlugin_ConstraintCollinear.cpp
SketchPlugin_ConstraintDistance.cpp
+ SketchPlugin_ConstraintDistanceHorizontal.cpp
+ SketchPlugin_ConstraintDistanceVertical.cpp
SketchPlugin_ConstraintEqual.cpp
SketchPlugin_Fillet.cpp
SketchPlugin_ConstraintHorizontal.cpp
SketchPlugin_ConstraintRigid.cpp
SketchPlugin_ConstraintTangent.cpp
SketchPlugin_ConstraintVertical.cpp
+ SketchPlugin_Ellipse.cpp
SketchPlugin_ExternalValidator.cpp
SketchPlugin_Feature.cpp
SketchPlugin_IntersectionPoint.cpp
SketchPlugin_Line.cpp
SketchPlugin_MacroArc.cpp
SketchPlugin_MacroCircle.cpp
+ SketchPlugin_MacroEllipse.cpp
SketchPlugin_MultiRotation.cpp
SketchPlugin_MultiTranslation.cpp
SketchPlugin_Plugin.cpp
TestConstraintCollinear.py
TestConstraintLength.py
TestConstraintDistance.py
+ TestConstraintDistanceHorizontal.py
+ TestConstraintDistanceVertical.py
+ TestConstraintDistanceBehavior.py
TestConstraintParallel.py
TestConstraintPerpendicular.py
TestConstraintRadius.py
TestConstraintFixed.py
TestConstraintHorizontal.py
+ TestConstraintHorizontalValidator.py
TestConstraintVertical.py
TestConstraintEqual.py
TestConstraintTangent.py
TestFilletInteracting.py
TestRectangle.py
TestProjection.py
+ TestProjectionIntoResult.py
TestSplit.py
TestHighload.py
TestSnowflake.py
TestTrimLine02.py
Test2229.py
Test2239.py
+ TestDistanceSignedVsUnsigned01.py
+ TestDistanceSignedVsUnsigned02.py
+ TestDistanceSignedVsUnsigned03.py
+ TestDistanceSignedVsUnsigned04.py
+ TestDistanceSignedVsUnsigned05.py
+ TestSignedDistancePointPoint.py
+ TestSignedDistancePointLine.py
)
+
+if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE})
+ ADD_UNIT_TESTS(
+ TestMovePoint.py
+ TestMoveLine.py
+ TestMoveCircle.py
+ TestMoveArc.py
+ TestMovementComplex.py
+ )
+endif()
\ No newline at end of file
setResult(aResult, 1);
}
-void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if(!aData->isValid()) {
- return;
- }
-
- bool aWasBlocked = aData->blockSendAttributeUpdated(true);
-
- std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- attribute(CENTER_ID()));
- if(aCenter->isInitialized()) {
- aCenter->move(theDeltaX, theDeltaY);
- }
-
- std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- attribute(START_ID()));
- if(aStart->isInitialized()) {
- aStart->move(theDeltaX, theDeltaY);
- }
-
- std::shared_ptr<GeomDataAPI_Point2D> anEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- attribute(END_ID()));
- if(anEnd->isInitialized()) {
- anEnd->move(theDeltaX, theDeltaY);
- }
-
- aData->blockSendAttributeUpdated(aWasBlocked);
-}
-
bool SketchPlugin_Arc::isFixed()
{
return data()->selection(EXTERNAL_ID())->context().get() != NULL;
/// Creates an arc-shape
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Updates the "reversed" flag
/// \param isReversed whether the arc will be reversed
void setReversed(bool isReversed);
setResult(aResult, 1);
}
-void SketchPlugin_Circle::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if(!aData->isValid()) {
- return;
- }
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(CENTER_ID()));
- if(aPoint->isInitialized()) {
- aPoint->move(theDeltaX, theDeltaY);
- }
-}
-
bool SketchPlugin_Circle::isFixed() {
return data()->selection(EXTERNAL_ID())->context().get() != NULL;
}
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Use plugin manager for features creation
SketchPlugin_Circle();
aValueAttr->setValue(anAngle);
}
-void SketchPlugin_ConstraintAngle::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- myFlyoutUpdate = true;
- std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
- GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
- aFlyoutAttr->setValue(aFlyoutAttr->x() + theDeltaX, aFlyoutAttr->y() + theDeltaY);
- myFlyoutUpdate = false;
-}
-
-
bool SketchPlugin_ConstraintAngle::compute(const std::string& theAttributeId)
{
if (theAttributeId != SketchPlugin_Constraint::FLYOUT_VALUE_PNT())
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Calculate current value of the angle
double calculateAngle();
{
}
-
-void SketchPlugin_ConstraintBase::move(const double theDeltaX, const double theDeltaY)
-{
-
-}
-
* \param theFeature sub-feature
*/
SKETCHPLUGIN_EXPORT virtual const void addSub(const FeaturePtr& theFeature);
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
/// Customize presentation of the feature
virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::collinearConstraint(this, sketch()->coordinatePlane(),
- thePrevious);
+ AISObjectPtr anAIS = SketcherPrs_Factory::collinearConstraint(
+ this, sketch(), sketch()->coordinatePlane(), thePrevious);
return anAIS;
}
data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SIGNED(), ModelAPI_AttributeBoolean::typeId());
}
void SketchPlugin_ConstraintDistance::colorConfigInfo(std::string& theSection, std::string& theName,
return anAIS;
}
-//*************************************************************************************
-void SketchPlugin_ConstraintDistance::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- // Recalculate a shift of flyout point in terms of local coordinates
- std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
- std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
- std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
- data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
- std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
- data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
-
- std::shared_ptr<GeomAPI_XY> aStartPnt;
- std::shared_ptr<GeomAPI_XY> aEndPnt;
- if (aPointA && aPointB) {
- aStartPnt = aPointA->pnt()->xy();
- aEndPnt = aPointB->pnt()->xy();
- } else if (aPointA) {
- FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
- SketchPlugin_Constraint::ENTITY_B());
- if (!aLine)
- return;
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointA->pnt();
- aStartPnt = aPoint->xy();
- aEndPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
- } else if (aPointB) {
- FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
- SketchPlugin_Constraint::ENTITY_A());
- if (!aLine)
- return;
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointB->pnt();
- aStartPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
- aEndPnt = aPoint->xy();
- } else
- return;
-
- std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
- double dX = aDir->dot(aLineDir->xy());
- double dY = -aDir->cross(aLineDir->xy());
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
- myFlyoutUpdate = true;
- if (aPoint->isInitialized()) {
- aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
- } else {
- aPoint->setValue(dX, dY);
- }
- myFlyoutUpdate = false;
-}
-
double SketchPlugin_ConstraintDistance::calculateCurrentDistance()
{
double aDistance = -1.;
return aDistance;
}
+bool SketchPlugin_ConstraintDistance::areAttributesInitialized()
+{
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointA =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointB =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+
+ if (!aPointA && !aPointB)
+ return false;
+ else if (aPointA || aPointB) {
+ FeaturePtr aLine;
+ if (!aPointA)
+ aLine = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
+ else if (!aPointB)
+ aLine = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
+ else // both points are initialized
+ return true;
+
+ if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
+ return false;
+ }
+ return true;
+}
+
void SketchPlugin_ConstraintDistance::attributeChanged(const std::string& theID)
{
if (theID == SketchPlugin_Constraint::ENTITY_A() ||
}
}
} else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
- myFlyoutUpdate = true;
// Recalculate flyout point in local coordinates of the distance constraint:
// the X coordinate is a length of projection of the flyout point on the
// line binding two distanced points
if (aEndPnt->distance(aStartPnt) < tolerance)
return;
+ myFlyoutUpdate = true;
std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
return MY_KIND;
}
+ /// \brief Shows whether the point-line distance should keep its sign
+ inline static const std::string& SIGNED()
+ {
+ static const std::string MY_SIGNED("SignedDistance");
+ return MY_SIGNED;
+ }
+
/// \brief Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object
/// \param theID identifier of changed attribute
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
protected:
/// Returns the current distance between the feature attributes
- double calculateCurrentDistance();
+ virtual double calculateCurrentDistance();
+
+ /// Check the attributes related to distanced points/features are initialized
+ bool areAttributesInitialized();
-private:
+protected:
bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point
};
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_ConstraintDistanceHorizontal.cpp
+// Created: 2 May 2017
+// Author: Artem ZHIDKOV
+
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+
+#include <SketcherPrs_Tools.h>
+#include <SketcherPrs_Factory.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_AttributeDouble.h>
+
+const double tolerance = 1e-7;
+
+
+SketchPlugin_ConstraintDistanceHorizontal::SketchPlugin_ConstraintDistanceHorizontal()
+ : SketchPlugin_ConstraintDistance()
+{
+}
+
+//*************************************************************************************
+void SketchPlugin_ConstraintDistanceHorizontal::initAttributes()
+{
+ data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+}
+
+//*************************************************************************************
+void SketchPlugin_ConstraintDistanceHorizontal::execute()
+{
+ AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE());
+ if (anAttrValue->isInitialized() || !areAttributesInitialized())
+ return;
+
+ double aDistance = calculateCurrentDistance();
+ anAttrValue->setValue(aDistance);
+}
+
+//*************************************************************************************
+AISObjectPtr SketchPlugin_ConstraintDistanceHorizontal::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
+ sketch()->coordinatePlane(),
+ thePrevious);
+ return anAIS;
+}
+
+double SketchPlugin_ConstraintDistanceHorizontal::calculateCurrentDistance()
+{
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointA =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointB =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+
+ return aPointB->x() - aPointA->x();
+}
+
+void SketchPlugin_ConstraintDistanceHorizontal::attributeChanged(const std::string& theID)
+{
+ if (theID == SketchPlugin_Constraint::ENTITY_A() ||
+ theID == SketchPlugin_Constraint::ENTITY_B())
+ {
+ AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE());
+ if (!aValueAttr->isInitialized() && areAttributesInitialized()) {
+ // only if it is not initialized, try to compute the current value
+ double aDistance = calculateCurrentDistance();
+ aValueAttr->setValue(aDistance);
+ }
+ } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+ // Recalculate flyout point in local coordinates of the distance constraint:
+ // the X coordinate is a length of projection of the flyout point on the
+ // line binding two distanced points
+ // or a line of projection of the distanced point onto the distanced segment
+ // the Y coordinate is a distance from the flyout point to the line
+ std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+
+ std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+ data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+ data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+
+ std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+ if (aEndPnt->distance(aStartPnt) < tolerance)
+ return;
+
+ myFlyoutUpdate = true;
+ std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aEndPnt);
+ double X = aFlyoutDir->x(); // Dot on OX axis
+ double Y = aFlyoutDir->y(); // Cross to OX axis
+ aFlyoutAttr->setValue(X, Y);
+ myFlyoutUpdate = false;
+ }
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_ConstraintDistanceHorizontal.h
+// Created: 2 May 2017
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_ConstraintDistanceHorizontal_H_
+#define SketchPlugin_ConstraintDistanceHorizontal_H_
+
+#include <SketchPlugin.h>
+#include <SketchPlugin_ConstraintDistance.h>
+
+/** \class SketchPlugin_ConstraintDistanceHorizontal
+ * \ingroup Plugins
+ * \brief Feature for creation of a new constraint which defines a horizontal distance between two points.
+ *
+ * This constraint has three attributes:
+ * SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B()
+ */
+class SketchPlugin_ConstraintDistanceHorizontal : public SketchPlugin_ConstraintDistance
+{
+public:
+ /// Distance constraint kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceHorizontal");
+ return MY_CONSTRAINT_DISTANCE_ID;
+ }
+
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_ConstraintDistanceHorizontal::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);
+
+ /// Called on change of any argument-attribute of this object
+ /// \param theID identifier of changed attribute
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintDistanceHorizontal();
+
+protected:
+ /// Returns the current distance between the feature attributes
+ virtual double calculateCurrentDistance();
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_ConstraintDistanceVertical.cpp
+// Created: 10 May 2017
+// Author: Artem ZHIDKOV
+
+#include <SketchPlugin_ConstraintDistanceVertical.h>
+
+#include <SketcherPrs_Tools.h>
+#include <SketcherPrs_Factory.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_AttributeDouble.h>
+
+const double tolerance = 1e-7;
+
+
+SketchPlugin_ConstraintDistanceVertical::SketchPlugin_ConstraintDistanceVertical()
+ : SketchPlugin_ConstraintDistance()
+{
+}
+
+//*************************************************************************************
+void SketchPlugin_ConstraintDistanceVertical::initAttributes()
+{
+ data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+}
+
+//*************************************************************************************
+void SketchPlugin_ConstraintDistanceVertical::execute()
+{
+ AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE());
+ if (anAttrValue->isInitialized() || !areAttributesInitialized())
+ return;
+
+ double aDistance = calculateCurrentDistance();
+ anAttrValue->setValue(aDistance);
+}
+
+//*************************************************************************************
+AISObjectPtr SketchPlugin_ConstraintDistanceVertical::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
+ sketch()->coordinatePlane(),
+ thePrevious);
+ return anAIS;
+}
+
+double SketchPlugin_ConstraintDistanceVertical::calculateCurrentDistance()
+{
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointA =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointB =
+ SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+
+ return aPointB->y() - aPointA->y();
+}
+
+void SketchPlugin_ConstraintDistanceVertical::attributeChanged(const std::string& theID)
+{
+ if (theID == SketchPlugin_Constraint::ENTITY_A() ||
+ theID == SketchPlugin_Constraint::ENTITY_B())
+ {
+ AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE());
+ if (!aValueAttr->isInitialized() && areAttributesInitialized()) {
+ // only if it is not initialized, try to compute the current value
+ double aDistance = calculateCurrentDistance();
+ aValueAttr->setValue(aDistance);
+ }
+ } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+ // Recalculate flyout point in local coordinates of the distance constraint:
+ // the X coordinate is a length of projection of the flyout point on the
+ // line binding two distanced points
+ // or a line of projection of the distanced point onto the distanced segment
+ // the Y coordinate is a distance from the flyout point to the line
+ std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+
+ std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
+ data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
+ std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
+ data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
+
+ std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
+
+ if (aEndPnt->distance(aStartPnt) < tolerance)
+ return;
+
+ std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aEndPnt);
+ myFlyoutUpdate = true;
+ double X = aFlyoutDir->y(); // Dot on OY axis
+ double Y = -aFlyoutDir->x(); // Cross to OY axis
+ aFlyoutAttr->setValue(X, Y);
+ myFlyoutUpdate = false;
+ }
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_ConstraintDistanceVertical.h
+// Created: 10 May 2017
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_ConstraintDistanceVertical_H_
+#define SketchPlugin_ConstraintDistanceVertical_H_
+
+#include <SketchPlugin.h>
+#include <SketchPlugin_ConstraintDistance.h>
+
+/** \class SketchPlugin_ConstraintDistanceVertical
+ * \ingroup Plugins
+ * \brief Feature for creation of a new constraint which defines a vertical distance between two points.
+ *
+ * This constraint has three attributes:
+ * SketchPlugin_Constraint::VALUE(), SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B()
+ */
+class SketchPlugin_ConstraintDistanceVertical : public SketchPlugin_ConstraintDistance
+{
+public:
+ /// Distance constraint kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistanceVertical");
+ return MY_CONSTRAINT_DISTANCE_ID;
+ }
+
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_ConstraintDistanceVertical::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);
+
+ /// Called on change of any argument-attribute of this object
+ /// \param theID identifier of changed attribute
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintDistanceVertical();
+
+protected:
+ /// Returns the current distance between the feature attributes
+ virtual double calculateCurrentDistance();
+};
+
+#endif
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::equalConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::equalConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::horisontalConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::horisontalConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
return anAIS;
}
-void SketchPlugin_ConstraintLength::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- AttributeRefAttrPtr aLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- attribute(SketchPlugin_Constraint::ENTITY_A()));
- if (!aLineAttr || !aLineAttr->isObject())
- return;
- FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
- if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
- return;
-
- // Recalculate a shift of flyout point in terms of local coordinates
- std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
- std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
- std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
- std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
- double dX = aDir->dot(aLineDir->xy());
- double dY = -aDir->cross(aLineDir->xy());
-
- myFlyoutUpdate = true;
- std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
- aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
- myFlyoutUpdate = false;
-}
-
void SketchPlugin_ConstraintLength::attributeChanged(const std::string& theID) {
if (theID == SketchPlugin_Constraint::ENTITY_A())
{
aValueAttr->setValue(aLength);
}
} else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
- myFlyoutUpdate = true;
// Recalculate flyout point in local coordinates of the line:
// the X coordinate is a length of projection of the flyout point on the line
// the Y coordinate is a distance from the point to the line
std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
+ myFlyoutUpdate = true;
std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
double X = aFlyoutDir->dot(aLineDir->xy());
#include <list>
+class GeomAPI_Pnt2d;
class GeomDataAPI_Point2D;
/** \class SketchPlugin_ConstraintLength
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object
/// \param theID identifier of changed attribute
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::middleConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::middleConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::parallelConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::parallelConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::perpendicularConstraint(this,
+ AISObjectPtr anAIS = SketcherPrs_Factory::perpendicularConstraint(this, sketch(),
sketch()->coordinatePlane(), thePrevious);
return anAIS;
}
return anAIS;
}
-void SketchPlugin_ConstraintRadius::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- myFlyoutUpdate = true;
- std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
- GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
- aFlyoutAttr->setValue(aFlyoutAttr->x() + theDeltaX, aFlyoutAttr->y() + theDeltaY);
- myFlyoutUpdate = false;
-}
-
void SketchPlugin_ConstraintRadius::attributeChanged(const std::string& theID) {
if (theID == SketchPlugin_Constraint::ENTITY_A()) {
std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object
/// \param theID identifier of changed attribute
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
{
if (!sketch())
return thePrevious;
- return SketcherPrs_Factory::rigidConstraint(this, sketch()->coordinatePlane(), thePrevious);
+ return SketcherPrs_Factory::rigidConstraint(this, sketch(),
+ sketch()->coordinatePlane(), thePrevious);
}
\ No newline at end of file
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::tangentConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::tangentConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::verticalConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::verticalConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_Ellipse.cpp
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+static const double tolerance = 1e-7;
+
+
+SketchPlugin_Ellipse::SketchPlugin_Ellipse()
+: SketchPlugin_SketchEntity()
+{
+}
+
+void SketchPlugin_Ellipse::initDerivedClassAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+
+ data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+}
+
+void SketchPlugin_Ellipse::execute()
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if(!aSketch) {
+ return;
+ }
+
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+ if (!aCenterAttr->isInitialized() ||
+ !aFocusAttr->isInitialized() ||
+ !aMajorRadiusAttr->isInitialized() ||
+ !aMinorRadiusAttr->isInitialized()) {
+ return;
+ }
+
+ double aMajorRadius = aMajorRadiusAttr->value();
+ double aMinorRadius = aMinorRadiusAttr->value();
+ if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
+ return;
+ }
+
+ // Make a visible point.
+ SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ // Make a visible ellipse.
+ std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+ std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+ std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape =
+ GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
+ aResult->setShape(anEllipseShape);
+ aResult->setIsInHistory(false);
+ setResult(aResult, 1);
+}
+
+bool SketchPlugin_Ellipse::isFixed() {
+ return data()->selection(EXTERNAL_ID())->context().get() != NULL;
+}
+
+void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
+ // the second condition for unability to move external segments anywhere
+ if (theID == EXTERNAL_ID() || isFixed()) {
+ std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+ if (!aSelection) {
+ // empty shape in selection shows that the shape is equal to context
+ ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+ if (anExtRes)
+ aSelection = anExtRes->shape();
+ }
+ // update arguments due to the selection value
+ if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+ std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
+ std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
+ aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+ aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
+
+ real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
+ real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius());
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_Ellipse.h
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_Ellipse_H_
+#define SketchPlugin_Ellipse_H_
+
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+
+/**\class SketchPlugin_Ellipse
+ * \ingroup Plugins
+ * \brief Feature for creation of the new ellipse in Sketch.
+ */
+class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity
+{
+ public:
+ /// Ellipse feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchEllipse");
+ return ID;
+ }
+
+ /// 2D point - center of the ellipse
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string ID("ellipse_center");
+ return ID;
+ }
+
+ /// 2D point - focus of the ellipse
+ inline static const std::string& FOCUS_ID()
+ {
+ static const std::string ID("ellipse_focus");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_minor_radius");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_Ellipse::ID();
+ return MY_KIND;
+ }
+
+ /// Returns true is sketch element is under the rigid constraint
+ SKETCHPLUGIN_EXPORT virtual bool isFixed();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Use plugin manager for features creation
+ SketchPlugin_Ellipse();
+
+protected:
+ /// \brief Initializes attributes of derived class.
+ virtual void initDerivedClassAttributes();
+};
+
+#endif
return true;
}
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) = 0;
-
/// Construction result is allways recomuted on the fly
SKETCHPLUGIN_EXPORT virtual bool isPersistentResult() {return false;}
}
}
-void SketchPlugin_IntersectionPoint::move(double theDeltaX, double theDeltaY)
-{
-}
-
void SketchPlugin_IntersectionPoint::attributeChanged(const std::string& theID)
{
if (theID == EXTERNAL_LINE_ID()) {
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object: for external point
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
}
}
-void SketchPlugin_Line::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (aData->attribute(START_ID()));
- aPoint1->move(theDeltaX, theDeltaY);
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (aData->attribute(END_ID()));
- aPoint2->move(theDeltaX, theDeltaY);
-}
-
std::string SketchPlugin_Line::processEvent(const std::shared_ptr<Events_Message>& theMessage)
{
std::string aFilledAttributeName;
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Apply information of the message to current object. It fills start attribute of
/// the currrent feature by last attribute of the message feature, build coincidence
/// if message has selected object
/// Creates an arc-shape
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY)
- {
- };
-
/// Reimplemented from ModelAPI_Feature::isMacro().
SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;};
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY)
- {};
-
/// Reimplemented from ModelAPI_Feature::isMacro().
/// \returns true
SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;};
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_MacroEllipse.cpp
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#include <SketchPlugin_MacroEllipse.h>
+
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_Tools.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_EventReentrantMessage.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Events.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Vertex.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+
+
+SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse()
+: SketchPlugin_SketchEntity(),
+ myMajorRadius(0.0),
+ myMinorRadius(0.0)
+{
+}
+
+void SketchPlugin_MacroEllipse::initAttributes()
+{
+ data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->
+ registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+}
+
+void SketchPlugin_MacroEllipse::execute()
+{
+ FeaturePtr anEllipse = createEllipseFeature();
+ constraintsForEllipse(anEllipse);
+
+ // message to init reentrant operation
+ static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
+ ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this));
+ aMessage->setCreatedFeature(anEllipse);
+ Events_Loop::loop()->send(aMessage);
+}
+
+void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
+{
+ static const int NB_POINTS = 3;
+ std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(),
+ MAJOR_AXIS_POINT_ID(),
+ PASSED_POINT_ID() };
+ std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(),
+ MAJOR_AXIS_POINT_REF_ID(),
+ PASSED_POINT_REF_ID() };
+
+ int aNbInitialized = 0;
+ std::shared_ptr<GeomAPI_Pnt2d> anEllipsePoints[NB_POINTS];
+
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+ if (!aPointAttr->isInitialized())
+ continue;
+
+ AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+ // calculate ellipse parameters
+ std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
+ std::shared_ptr<GeomAPI_Shape> aTangentCurve;
+ SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+ aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+
+ anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ }
+
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+ if (aNbInitialized == 2) {
+ std::shared_ptr<GeomAPI_Dir2d> aXDir(new GeomAPI_Dir2d(
+ anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+ anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+ double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+ } else if (aNbInitialized == 3) {
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
+ }
+
+ if (!anEllipse || anEllipse->implPtr<void>() == 0)
+ return;
+
+ myCenter = anEllipse->center();
+ myFocus = anEllipse->firstFocus();
+ myMajorRadius = anEllipse->majorRadius();
+ myMinorRadius = anEllipse->minorRadius();
+
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ // center attribute is used in processEvent() to set reference to reentrant arc
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->setValue(myCenter);
+ aMajorRadiusAttr->setValue(myMajorRadius);
+ aMinorRadiusAttr->setValue(myMinorRadius);
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+}
+
+std::string SketchPlugin_MacroEllipse::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ std::string aFilledAttributeName;
+
+ ReentrantMessagePtr aReentrantMessage =
+ std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+ if (aReentrantMessage) {
+ FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+ ObjectPtr anObject = aReentrantMessage->selectedObject();
+ AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+ std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+
+ if (aClickedPoint && (anObject || anAttribute)) {
+ aFilledAttributeName = CENTER_POINT_ID();
+ std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+
+ // fill 2d point attribute
+ AttributePoint2DPtr aPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(aFilledAttributeName));
+ aPointAttr->setValue(aClickedPoint);
+
+ // fill reference attribute
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
+ if (anAttribute) {
+ if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
+ if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
+ anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID());
+ }
+ aRefAttr->setAttr(anAttribute);
+ }
+ else if (anObject.get()) {
+ // if presentation of previous reentrant macro arc is used, the object is invalid,
+ // we should use result of previous feature of the message(Arc)
+ if (!anObject->data()->isValid())
+ anObject = aCreatedFeature->lastResult();
+ aRefAttr->setObject(anObject);
+ }
+ }
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ }
+ return aFilledAttributeName;
+}
+
+void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature)
+{
+ // Create constraints.
+ SketchPlugin_Tools::createConstraint(
+ this, CENTER_POINT_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+ ObjectPtr(), false);
+ SketchPlugin_Tools::createConstraint(
+ this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(),
+ theEllipseFeature->lastResult(), true);
+ SketchPlugin_Tools::createConstraint(
+ this, PASSED_POINT_REF_ID(), AttributePtr(),
+ theEllipseFeature->lastResult(), true);
+}
+
+FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
+{
+ FeaturePtr aEllipseFeature = sketch()->addFeature(SketchPlugin_Ellipse::ID());
+
+ AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()));
+ aCenterAttr->setValue(myCenter->x(), myCenter->y());
+
+ AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID()));
+ aFocusAttr->setValue(myFocus->x(), myFocus->y());
+
+ aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+ aEllipseFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(myMinorRadius);
+
+ aEllipseFeature->boolean(SketchPlugin_Ellipse::AUXILIARY_ID())->setValue(
+ boolean(AUXILIARY_ID())->value());
+
+ aEllipseFeature->execute();
+ return aEllipseFeature;
+}
+
+AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious)
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch || !myCenter || myMajorRadius == 0)
+ return AISObjectPtr();
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
+ std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape =
+ GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, myMajorRadius, myMinorRadius);
+ GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
+ if (!anEllipseShape.get() || !aCenterPointShape.get())
+ return AISObjectPtr();
+
+ std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+ aShapes.push_back(anEllipseShape);
+ aShapes.push_back(aCenterPointShape);
+
+ std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+ AISObjectPtr anAIS = thePrevious;
+ if (!anAIS)
+ anAIS.reset(new GeomAPI_AISObject());
+ anAIS->createShape(aCompound);
+ return anAIS;
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchPlugin_MacroEllipse.h
+// Created: 26 April 2017
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_MacroEllipse_H_
+#define SketchPlugin_MacroEllipse_H_
+
+#include <ModelAPI_IReentrant.h>
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+#include <GeomAPI_IPresentable.h>
+
+////class GeomAPI_Circ2d;
+class GeomAPI_Pnt2d;
+
+/**\class SketchPlugin_MacroEllipse
+ * \ingroup Plugins
+ * \brief Feature for creation of the new ellipse in Sketch.
+ */
+class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity,
+ public GeomAPI_IPresentable,
+ public ModelAPI_IReentrant
+{
+ public:
+ /// Ellipse feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchMacroEllipse");
+ return ID;
+ }
+
+ /// 2D point - center of the ellipse.
+ inline static const std::string& CENTER_POINT_ID()
+ {
+ static const std::string ID("center_point");
+ return ID;
+ }
+
+ /// Reference for center point selection.
+ inline static const std::string& CENTER_POINT_REF_ID()
+ {
+ static const std::string ID("center_point_ref");
+ return ID;
+ }
+
+ /// 2D point - major axis point of the ellipse.
+ inline static const std::string& MAJOR_AXIS_POINT_ID()
+ {
+ static const std::string ID("major_axis_point");
+ return ID;
+ }
+
+ /// Reference for major axis point selection.
+ inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+ {
+ static const std::string ID("major_axis_point_ref");
+ return ID;
+ }
+
+ /// 2D point - passed point of the ellipse
+ inline static const std::string& PASSED_POINT_ID()
+ {
+ static const std::string ID("passed_point");
+ return ID;
+ }
+
+ /// Reference for passed point selection.
+ inline static const std::string& PASSED_POINT_REF_ID()
+ {
+ static const std::string ID("passed_point_ref");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_minor_radius");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_MacroEllipse::ID();
+ return MY_KIND;
+ }
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes.
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Returns the AIS preview
+ virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Reimplemented from ModelAPI_Feature::isMacro().
+ /// \returns true
+ SKETCHPLUGIN_EXPORT virtual bool isMacro() const
+ {return true;}
+
+ SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const
+ {return false;}
+
+ /// Apply information of the message to current object. It fills reference object,
+ /// tangent type and tangent point refence in case of tangent arc
+ virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ /// Use plugin manager for features creation
+ SketchPlugin_MacroEllipse();
+
+private:
+ void constraintsForEllipse(FeaturePtr theEllipseFeature);
+
+ FeaturePtr createEllipseFeature();
+
+private:
+ std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+ std::shared_ptr<GeomAPI_Pnt2d> myFocus;
+ double myMajorRadius;
+ double myMinorRadius;
+};
+
+#endif
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::rotateConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::rotateConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
if (!sketch())
return thePrevious;
- AISObjectPtr anAIS = SketcherPrs_Factory::translateConstraint(this, sketch()->coordinatePlane(),
+ AISObjectPtr anAIS = SketcherPrs_Factory::translateConstraint(this, sketch(),
+ sketch()->coordinatePlane(),
thePrevious);
return anAIS;
}
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_Fillet.h>
#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_Split.h>
#include <SketchPlugin_Validators.h>
#include <SketchPlugin_ExternalValidator.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_MacroEllipse.h>
#include <Events_Loop.h>
#include <GeomDataAPI_Dir.h>
new SketchPlugin_ArcEndPointValidator);
aFactory->registerValidator("SketchPlugin_ArcEndPointIntersectionValidator",
new SketchPlugin_ArcEndPointIntersectionValidator);
+ aFactory->registerValidator("SketchPlugin_HasNoConstraint", new SketchPlugin_HasNoConstraint);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new SketchPlugin_ConstraintCollinear);
} else if (theFeatureID == SketchPlugin_ConstraintDistance::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintDistance);
+ } else if (theFeatureID == SketchPlugin_ConstraintDistanceHorizontal::ID()) {
+ return FeaturePtr(new SketchPlugin_ConstraintDistanceHorizontal);
+ } else if (theFeatureID == SketchPlugin_ConstraintDistanceVertical::ID()) {
+ return FeaturePtr(new SketchPlugin_ConstraintDistanceVertical);
} else if (theFeatureID == SketchPlugin_ConstraintLength::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintLength);
} else if (theFeatureID == SketchPlugin_ConstraintParallel::ID()) {
return FeaturePtr(new SketchPlugin_MacroArc);
} else if (theFeatureID == SketchPlugin_MacroCircle::ID()) {
return FeaturePtr(new SketchPlugin_MacroCircle);
+ } else if (theFeatureID == SketchPlugin_Ellipse::ID()) {
+ return FeaturePtr(new SketchPlugin_Ellipse);
+ } else if (theFeatureID == SketchPlugin_MacroEllipse::ID()) {
+ return FeaturePtr(new SketchPlugin_MacroEllipse);
}
// feature of such kind is not found
return FeaturePtr();
aMsg->setState(SketchPlugin_Line::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_Ellipse::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Projection::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCoincidence::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCollinear::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Trim::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane);
// SketchRectangle is a python feature, so its ID is passed just as a string
aMsg->setState("SketchRectangle", aHasSketchPlane);
}
}
}
-void SketchPlugin_Point::move(double theDeltaX, double theDeltaY)
-{
- std::shared_ptr<ModelAPI_Data> aData = data();
- if (!aData->isValid())
- return;
-
- std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(SketchPlugin_Point::COORD_ID()));
- aPoint1->move(theDeltaX, theDeltaY);
-}
-
bool SketchPlugin_Point::isFixed() {
return data()->selection(EXTERNAL_ID())->context().get() != NULL;
}
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object: for external point
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
#include <SketchPlugin_Sketch.h>
#include <SketchPlugin_ConstraintRigid.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Vertex.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomDataAPI_Point2D.h>
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+ data()->addAttribute(INCLUDE_INTO_RESULT(), ModelAPI_AttributeBoolean::typeId());
+
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), AUXILIARY_ID());
}
computeProjection(EXTERNAL_FEATURE_ID());
}
-void SketchPlugin_Projection::move(double theDeltaX, double theDeltaY)
-{
- // feature cannot be moved
-}
-
void SketchPlugin_Projection::attributeChanged(const std::string& theID)
{
if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) {
}
}
+static bool isValidProjectionType(FeaturePtr theProjection,
+ GeomEdgePtr theEdge,
+ GeomVertexPtr theVertex)
+{
+ if (theVertex && theProjection->getKind() == SketchPlugin_Point::ID())
+ return true;
+ if (theEdge) {
+ if (theEdge->isLine() && theProjection->getKind() == SketchPlugin_Line::ID())
+ return true;
+ else if (theEdge->isCircle() && theProjection->getKind() == SketchPlugin_Circle::ID())
+ return true;
+ else if (theEdge->isArc() && theProjection->getKind() == SketchPlugin_Arc::ID())
+ return true;
+ }
+ return false;
+}
+
void SketchPlugin_Projection::computeProjection(const std::string& theID)
{
AttributeSelectionPtr aExtFeature =
std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(attribute(EXTERNAL_FEATURE_ID()));
- std::shared_ptr<GeomAPI_Edge> anEdge;
- if (aExtFeature && aExtFeature->value() && aExtFeature->value()->isEdge()) {
- anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->value()));
- } else if (aExtFeature->context() && aExtFeature->context()->shape() &&
- aExtFeature->context()->shape()->isEdge()) {
- anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->context()->shape()));
+ GeomShapePtr aShape;
+ GeomEdgePtr anEdge;
+ GeomVertexPtr aVertex;
+ if (aExtFeature)
+ aShape = aExtFeature->value();
+ if (!aShape && aExtFeature->context())
+ aShape = aExtFeature->context()->shape();
+ if (aShape) {
+ if (aShape->isEdge())
+ anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
+ else if (aShape->isVertex())
+ aVertex = GeomVertexPtr(new GeomAPI_Vertex(aShape));
}
- if (!anEdge.get())
+ if (!anEdge && !aVertex)
return;
AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
// if the type of feature differs with already selected, remove it and create once again
bool hasPrevProj = aProjection.get() != 0;
- if (hasPrevProj) {
- if ((anEdge->isLine() && aProjection->getKind() != SketchPlugin_Line::ID()) ||
- (anEdge->isCircle() && aProjection->getKind() != SketchPlugin_Circle::ID()) ||
- (anEdge->isArc() && aProjection->getKind() != SketchPlugin_Arc::ID())) {
- DocumentPtr aDoc = sketch()->document();
-
- std::set<FeaturePtr> aFeaturesToBeRemoved;
- aFeaturesToBeRemoved.insert(aProjection);
- ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
- aProjection = FeaturePtr();
- aRefAttr->setObject(aProjection);
- }
+ if (hasPrevProj && !isValidProjectionType(aProjection, anEdge, aVertex)) {
+ DocumentPtr aDoc = sketch()->document();
+
+ std::set<FeaturePtr> aFeaturesToBeRemoved;
+ aFeaturesToBeRemoved.insert(aProjection);
+ ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
+ aProjection = FeaturePtr();
+ aRefAttr->setObject(aProjection);
+ hasPrevProj = false;
}
std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
}
- if (anEdge->isLine()) {
+ if (aVertex) {
+ std::shared_ptr<GeomAPI_Pnt> aPrjPnt = aSketchPlane->project(aVertex->point());
+ std::shared_ptr<GeomAPI_Pnt2d> aPntInSketch = sketch()->to2D(aPrjPnt);
+
+ if (!hasPrevProj)
+ aProjection = sketch()->addFeature(SketchPlugin_Point::ID());
+
+ // update coordinates of projection
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch);
+ }
+ else if (anEdge->isLine()) {
std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
+ bool isInversed = aCircle->normal()->dot(aSketchPlane->direction()) < 0.;
+
if (!hasPrevProj)
aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
+ bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
+
// update attributes of projection
std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aStartPnt->setValue(aFirstInSketch);
aEndPnt->setValue(aLastInSketch);
aCenterPnt->setValue(aCenterInSketch);
+ aProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed);
+
+ aProjection->data()->blockSendAttributeUpdated(aWasBlocked, false);
}
aProjection->boolean(COPY_ID())->setValue(true);
return MY_PROJ_FEATURE_ID;
}
+ static const std::string& INCLUDE_INTO_RESULT()
+ {
+ static std::string MY_INCLUDE("IncludeToResult");
+ return MY_INCLUDE;
+ }
+
/// Returns true because projected feature is always external
virtual bool isFixed()
{ return true; }
/// Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
-
/// Called on change of any argument-attribute of this object: for external point
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
#include <SketchPlugin_Sketch.h>
#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Projection.h>
#include <SketchPlugin_SketchEntity.h>
#include <SketchPlugin_Tools.h>
if (aFeature) {
if (!aFeature->sketch()) // on load document the back references are missed
aFeature->setSketch(this);
- // do not include the external edges into the result
+ // do not include into the result the external edges with disabled flag "Include into result"
if (aFeature->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID())) {
- if (aFeature->data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->context())
- continue;
+ if (aFeature->data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->context()) {
+ AttributeBooleanPtr aKeepResult =
+ aFeature->boolean(SketchPlugin_Projection::INCLUDE_INTO_RESULT());
+ if (!aKeepResult || !aKeepResult->value())
+ continue;
+ }
}
// do not include the construction entities in the result
if (aFeature->data()->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID())) {
/// Request for initialization of data model of the feature: adding all attributes
SKETCHPLUGIN_EXPORT virtual void initAttributes();
- /// Moves the feature
- /// \param theDeltaX the delta for X coordinate is moved
- /// \param theDeltaY the delta for Y coordinate is moved
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY)
- {
- }
-
/// Converts a 2D sketch space point into point in 3D space
/// \param theX an X coordinate
/// \param theY an Y coordinate
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature : Empty
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {};
-
/// Apply information of the message to current object. It fills selected point and object
virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
- /// Moves the feature : Empty
- SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) {};
-
/// Apply information of the message to current object. It fills selected point and object
virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
AttributeSelectionPtr aFeatureAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
std::shared_ptr<GeomAPI_Edge> anEdge;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature;
if (aFeatureAttr.get()) {
GeomShapePtr aVal = aFeatureAttr->value();
ResultPtr aRes = aFeatureAttr->context();
- if(aFeatureAttr->value() && aFeatureAttr->value()->isEdge()) {
+ if(aVal && aVal->isEdge()) {
anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->value()));
- } else if(aFeatureAttr->context() && aFeatureAttr->context()->shape() &&
- aFeatureAttr->context()->shape()->isEdge()) {
+ } else if(aRes && aRes->shape() && aRes->shape()->isEdge()) {
anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->context()->shape()));
}
+
+ // try to convert result to sketch feature
+ if (aRes) {
+ aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(ModelAPI_Feature::feature(aRes));
+ }
}
if (!anEdge) {
- theError = "The attribute %1 should be an edge";
+ // check a vertex has been selected
+ if (aFeatureAttr->value() && aFeatureAttr->value()->isVertex())
+ return true;
+ else {
+ ResultPtr aRes = aFeatureAttr->context();
+ if (aRes && aRes->shape() && aRes->shape()->isVertex())
+ return true;
+ }
+
+ theError = "The attribute %1 should be an edge or vertex";
theError.arg(theAttribute->id());
return false;
}
theError = "There is no sketch referring to the current feature";
return false;
}
+ if (aSketchFeature && aSketch.get() == aSketchFeature->sketch()) {
+ theError = "Unable to project feature from the same sketch";
+ return false;
+ }
std::shared_ptr<GeomAPI_Pln> aPlane = aSketch->plane();
std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
if (anEdge->isLine()) {
std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
std::shared_ptr<GeomAPI_Dir> aLineDir = aLine->direction();
- std::shared_ptr<GeomAPI_Pnt> aLineLoc = aLine->location();
- double aDot = aNormal->dot(aLineDir);
- double aDist = aLineLoc->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz());
- bool aValid = (fabs(aDot) >= tolerance && fabs(aDot) < 1.0 - tolerance) ||
- (fabs(aDot) < tolerance && fabs(aDist) > tolerance);
+ double aDot = fabs(aNormal->dot(aLineDir));
+ bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance;
if (!aValid)
theError = "Error: Edge is already in the sketch plane.";
return aValid;
else if (anEdge->isCircle() || anEdge->isArc()) {
std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
std::shared_ptr<GeomAPI_Dir> aCircNormal = aCircle->normal();
- std::shared_ptr<GeomAPI_Pnt> aCircCenter = aCircle->center();
double aDot = fabs(aNormal->dot(aCircNormal));
- double aDist = aCircCenter->xyz()->decreased(anOrigin->xyz())->dot(aNormal->xyz());
- bool aValid = fabs(aDot - 1.0) < tolerance * tolerance && fabs(aDist) > tolerance;
+ bool aValid = fabs(aDot - 1.0) < tolerance * tolerance;
if (!aValid)
theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane."
: "Error: Arc is already in the sketch plane.");
return false;
}
+
+bool SketchPlugin_HasNoConstraint::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ std::set<std::string> aFeatureKinds;
+ for (std::list<std::string>::const_iterator anArgIt = theArguments.begin();
+ anArgIt != theArguments.end(); anArgIt++) {
+ aFeatureKinds.insert(*anArgIt);
+ }
+
+ if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
+ theError = "The attribute with the %1 type is not processed";
+ theError.arg(theAttribute->attributeType());
+ return false;
+ }
+
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
+ (theAttribute);
+ bool isObject = aRefAttr->isObject();
+ if (!isObject) {
+ theError = "It uses an empty object";
+ return false;
+ }
+ ObjectPtr anObject = aRefAttr->object();
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+ if (!aFeature.get()) {
+ theError = "The feature of the checked attribute is empty";
+ return false;
+ }
+
+ FeaturePtr aCurrentFeature = ModelAPI_Feature::feature(aRefAttr->owner());
+
+ std::set<AttributePtr> aRefsList = anObject->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator anIt = aRefsList.begin();
+ for (; anIt != aRefsList.end(); anIt++) {
+ FeaturePtr aRefFeature = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRefFeature.get() && aCurrentFeature != aRefFeature &&
+ aFeatureKinds.find(aRefFeature->getKind()) != aFeatureKinds.end())
+ return false; // constraint is found, that means that the check is not valid
+ }
+ return true;
+}
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_HasNoConstraint
+ * \ingroup Validators
+ * \brief Validator for checking whether the feature has constraint.
+ *
+ * Checks that feature of the attribute does not have constraint with some kinds.
+ * The kinds of constraints should be described in parameters of the validator
+ * Validator processes the ModelAPI_AttributeRefAttr attribute kind
+ */
+class SketchPlugin_HasNoConstraint: 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;
+};
+
#endif
aSession.startOperation()
anArcStartPoint.setValue(sx, sy+aDelta) # move start point
aSession.finishOperation()
- model.assertSketchArc(aSketchArc)
+ model.assertArcValidity(aSketchArc)
for aDelta in range(20, -1, -1):
aSession.startOperation()
anArcStartPoint.setValue(sx, sy+aDelta) # move start point
aSession.finishOperation()
- model.assertSketchArc(aSketchArc)
+ model.assertArcValidity(aSketchArc)
#=========================================================================
# Test that movement of end point of arc does not break the arc
#=========================================================================
aSession.startOperation()
anArcEndPoint.setValue(sx+aDelta, sy) # move end point
aSession.finishOperation()
- model.assertSketchArc(aSketchArc)
+ model.assertArcValidity(aSketchArc)
for aDelta in range(20, -1, -1):
aSession.startOperation()
anArcEndPoint.setValue(sx+aDelta, sy) # move end point
aSession.finishOperation()
- model.assertSketchArc(aSketchArc)
+ model.assertArcValidity(aSketchArc)
aFeature.real("x").setValue(0.)
aFeature.real("y").setValue(0.)
aFeature.real("z").setValue(0.)
+aFeature.string("creation_method").setValue("by_xyz")
anOriginName = aFeature.name()
aSession.finishOperation()
#=========================================================================
__updated__ = "2014-10-28"
-def distancePointLine(point, line):
- """
- subroutine to calculate distance between point and line
- result of calculated distance is has 10**-5 precision
- """
- aStartPoint = geomDataAPI_Point2D(line.attribute("StartPoint"))
- aEndPoint = geomDataAPI_Point2D(line.attribute("EndPoint"))
- # orthogonal direction
- aDirX = -(aEndPoint.y() - aStartPoint.y())
- aDirY = (aEndPoint.x() - aStartPoint.x())
- aLen = math.sqrt(aDirX**2 + aDirY**2)
- aDirX = aDirX / aLen
- aDirY = aDirY / aLen
- aVecX = point.x() - aStartPoint.x()
- aVecY = point.y() - aStartPoint.y()
- return round(math.fabs(aVecX * aDirX + aVecY * aDirY), 5)
-
aSession = ModelAPI_Session.get()
aDocument = aSession.moduleDocument()
#=========================================================================
# Add distance between point and line
#=========================================================================
PT_LINE_DIST = 50.
-aDist = distancePointLine(aSketchPointCoords, aSketchLine)
+aDist = model.distancePointLine(aSketchPointCoords, aSketchLine)
aSession.startOperation()
aConstraint = aSketchFeature.addFeature("SketchConstraintDistance")
aDistance = aConstraint.real("ConstraintValue")
aSession.startOperation()
aDistance.setValue(PT_LINE_DIST)
aSession.finishOperation()
-assert (math.fabs(distancePointLine(aSketchPointCoords, aSketchLine) - PT_LINE_DIST) < 1.e-10)
+assert (math.fabs(model.distancePointLine(aSketchPointCoords, aSketchLine) - PT_LINE_DIST) < 1.e-10)
assert (model.dof(aSketchFeature) == 5)
#=========================================================================
# Set distance between line boundaries
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-7
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+DistanceParam = model.addParameter(Part_1_doc, "distance", "10.")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchRectangle_1 = Sketch_1.addRectangle(20., 20., 70., 50.)
+[SketchLine_1, SketchLine_2, SketchLine_3, SketchLine_4] = SketchRectangle_1.lines()
+firstPoint = SketchAPI_Line(SketchLine_2).startPoint()
+secondPoint = SketchAPI_Line(SketchLine_3).endPoint()
+model.do()
+
+# =============================================================================
+# Test 1.
+# =============================================================================
+# horizontal distance constraint
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(firstPoint, secondPoint, "distance")
+model.do()
+
+# changing the parameter
+for param in range(-30, 31, 2):
+ DistanceParam.setValue(param)
+ model.do()
+ dist = secondPoint.x() - firstPoint.x()
+ assert math.fabs(dist - param) < TOLERANCE, "Incorrect horizontal distance {}, expected {}".format(dist, param)
+
+model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceHorizontal", 1)
+
+# remove horizontal distance constraint
+Part_1_doc.removeFeature(SketchConstraintDistanceHorizontal_1.feature())
+model.do()
+
+# =============================================================================
+# Test 2.
+# =============================================================================
+# Vertical distance constraint
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(firstPoint, secondPoint, "distance")
+model.do()
+
+# changing the parameter
+for param in range(-30, 31, 2):
+ DistanceParam.setValue(param)
+ model.do()
+ dist = secondPoint.y() - firstPoint.y()
+ assert math.fabs(dist - param) < TOLERANCE, "Incorrect vertical distance {}, expected {}".format(dist, param)
+
+model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+model.testNbSubFeatures(Sketch_1, "SketchConstraintDistanceVertical", 1)
+
+# remove verticel distance constraint
+Part_1_doc.removeFeature(SketchConstraintDistanceVertical_1.feature())
+model.do()
+
+# =============================================================================
+# Test 3.
+# =============================================================================
+# distance constraint
+SketchConstraintDistance_1 = Sketch_1.setDistance(firstPoint, secondPoint, "distance")
+model.do()
+
+# changing the parameter
+for param in range(-30, 31, 2):
+ DistanceParam.setValue(param)
+ model.do()
+ if param <= 0:
+ assert SketchConstraintDistance_1.feature().error() != '', "ERROR: Sketch should not be valid due to negative distance value"
+ else:
+ dist = model.distancePointPoint(firstPoint, secondPoint)
+ assert math.fabs(dist - math.fabs(param)) < TOLERANCE, "Incorrect distance {}, expected {}".format(dist, math.fabs(param))
+
+model.testNbSubFeatures(Sketch_1, "SketchLine", 4)
+model.testNbSubFeatures(Sketch_1, "SketchConstraintDistance", 1)
+# leave distance constraint alive
+
+model.end()
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ TestConstraintDistanceHorizontal.py
+ Unit test of SketchPlugin_ConstraintDistanceHorizontal class
+
+ SketchPlugin_ConstraintDistanceHorizontal
+ static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance");
+ data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+"""
+
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+from salome.shaper import model
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+
+__updated__ = "2017-05-10"
+
+
+def horizontalDistance(point1, point2):
+ """
+ subroutine to calculate signed distance between two points
+ """
+ return point2.x() - point1.x()
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+#=========================================================================
+# Create two movable and one fixed point
+#=========================================================================
+aSession.startOperation()
+aPoint1 = aSketchFeature.addFeature("SketchPoint")
+aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates"))
+aPoint1Coords.setValue(50., 50.)
+aSession.finishOperation()
+aSession.startOperation()
+aPoint2 = aSketchFeature.addFeature("SketchPoint")
+aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates"))
+aPoint2Coords.setValue(70., 70.)
+aSession.finishOperation()
+aSession.startOperation()
+anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin"))
+anOriginShape = anOriginResult.shape()
+anExtPoint = aSketchFeature.addFeature("SketchPoint")
+anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates"))
+anExtCoords.setValue(0., 0.)
+anExtPoint.selection("External").setValue(anOriginResult, anOriginShape)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 4)
+
+#=========================================================================
+# Create a constraint to keep horizontal distance between movable points
+#=========================================================================
+DISTANCE1 = 25.
+aSession.startOperation()
+aHDist1 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+aDistance = aHDist1.real("ConstraintValue")
+refattrA = aHDist1.refattr("ConstraintEntityA")
+refattrB = aHDist1.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setObject(aPoint1.lastResult())
+refattrB.setObject(aPoint2.lastResult())
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 3)
+# set flyout point then abort operation, after that check the Distance is correct
+aSession.startOperation()
+aFlyoutPoint = geomDataAPI_Point2D(aHDist1.attribute("ConstraintFlyoutValuePnt"))
+aFlyoutPoint.setValue(50.0, 100.0)
+aSession.abortOperation()
+assert (refattrA.isInitialized())
+assert (refattrB.isInitialized())
+assert (aDistance.isInitialized())
+aSession.startOperation()
+aDistance.setValue(DISTANCE1)
+aSession.finishOperation()
+assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+assert (model.dof(aSketchFeature) == 3)
+#=========================================================================
+# Change a distance value
+#=========================================================================
+d = DISTANCE1 + 20.
+dStep = -5.
+while d >= -30.:
+ aSession.startOperation()
+ DISTANCE1 = d
+ aDistance.setValue(DISTANCE1)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ d += dStep
+assert (model.dof(aSketchFeature) == 3)
+
+#=========================================================================
+# Create a constraint to keep horizontal distance between fixed and movable points
+#=========================================================================
+DISTANCE2 = 50.
+aSession.startOperation()
+aHDist2 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+aDistance = aHDist2.real("ConstraintValue")
+refattrA = aHDist2.refattr("ConstraintEntityA")
+refattrB = aHDist2.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setObject(anExtPoint.lastResult())
+refattrB.setAttr(aPoint1Coords)
+aDistance.setValue(DISTANCE2)
+aSession.finishOperation()
+assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+assert (model.dof(aSketchFeature) == 2)
+#=========================================================================
+# Change a distance value (check previous constraint is applied too)
+#=========================================================================
+d = DISTANCE2
+dStep = -5.
+while d >= -50.:
+ aSession.startOperation()
+ DISTANCE2 = d
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ d += dStep
+assert (model.dof(aSketchFeature) == 2)
+
+#=========================================================================
+# Remove first distance
+#=========================================================================
+aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()]
+aSession.startOperation()
+aDocument.removeFeature(aHDist1)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 3)
+aSession.startOperation()
+DISTANCE2 = 20.
+aDistance.setValue(DISTANCE2)
+aSession.finishOperation()
+assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1]
+
+#=========================================================================
+# Create line and set horizontal distance between line boundaries
+#=========================================================================
+aSession.startOperation()
+aLine = aSketchFeature.addFeature("SketchLine")
+aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+aStartPoint.setValue(50., 0.)
+aEndPoint.setValue(100., 20.)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 7)
+
+DISTANCE3 = 50.
+aSession.startOperation()
+aHDist3 = aSketchFeature.addFeature("SketchConstraintDistanceHorizontal")
+aDistance = aHDist3.real("ConstraintValue")
+refattrA = aHDist3.refattr("ConstraintEntityA")
+refattrB = aHDist3.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setAttr(aStartPoint)
+refattrB.setAttr(aEndPoint)
+aDistance.setValue(DISTANCE3)
+aSession.finishOperation()
+assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
+assert (model.dof(aSketchFeature) == 6)
+#=========================================================================
+# Change a distance value
+#=========================================================================
+d = DISTANCE3
+dStep = -5.
+while d >= -50.:
+ aSession.startOperation()
+ DISTANCE3 = d
+ aDistance.setValue(DISTANCE3)
+ aSession.finishOperation()
+ assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ d += dStep
+assert (model.dof(aSketchFeature) == 6)
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+assert(model.checkPythonDump())
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ TestConstraintDistanceVertical.py
+ Unit test of SketchPlugin_ConstraintDistanceVertical class
+
+ SketchPlugin_ConstraintDistanceVertical
+ static const std::string MY_CONSTRAINT_DISTANCE_ID("SketchConstraintDistance");
+ data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
+"""
+
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+from salome.shaper import model
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+
+__updated__ = "2017-05-10"
+
+
+def verticalDistance(point1, point2):
+ """
+ subroutine to calculate signed distance between two points
+ """
+ return point2.y() - point1.y()
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+#=========================================================================
+# Create two movable and one fixed point
+#=========================================================================
+aSession.startOperation()
+aPoint1 = aSketchFeature.addFeature("SketchPoint")
+aPoint1Coords = geomDataAPI_Point2D(aPoint1.attribute("PointCoordinates"))
+aPoint1Coords.setValue(50., 50.)
+aSession.finishOperation()
+aSession.startOperation()
+aPoint2 = aSketchFeature.addFeature("SketchPoint")
+aPoint2Coords = geomDataAPI_Point2D(aPoint2.attribute("PointCoordinates"))
+aPoint2Coords.setValue(70., 70.)
+aSession.finishOperation()
+aSession.startOperation()
+anOriginResult = modelAPI_Result(aDocument.objectByName("Construction", "Origin"))
+anOriginShape = anOriginResult.shape()
+anExtPoint = aSketchFeature.addFeature("SketchPoint")
+anExtCoords = geomDataAPI_Point2D(anExtPoint.attribute("PointCoordinates"))
+anExtCoords.setValue(0., 0.)
+anExtPoint.selection("External").setValue(anOriginResult, anOriginShape)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 4)
+
+#=========================================================================
+# Create a constraint to keep vertical distance between movable points
+#=========================================================================
+DISTANCE1 = 25.
+aSession.startOperation()
+aVDist1 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+aDistance = aVDist1.real("ConstraintValue")
+refattrA = aVDist1.refattr("ConstraintEntityA")
+refattrB = aVDist1.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setObject(aPoint1.lastResult())
+refattrB.setObject(aPoint2.lastResult())
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 3)
+# set flyout point then abort operation, after that check the Distance is correct
+aSession.startOperation()
+aFlyoutPoint = geomDataAPI_Point2D(aVDist1.attribute("ConstraintFlyoutValuePnt"))
+aFlyoutPoint.setValue(50.0, 100.0)
+aSession.abortOperation()
+assert (refattrA.isInitialized())
+assert (refattrB.isInitialized())
+assert (aDistance.isInitialized())
+aSession.startOperation()
+aDistance.setValue(DISTANCE1)
+aSession.finishOperation()
+assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+assert (model.dof(aSketchFeature) == 3)
+#=========================================================================
+# Change a distance value
+#=========================================================================
+d = DISTANCE1 + 20.
+dStep = -5.
+while d >= -30.:
+ aSession.startOperation()
+ DISTANCE1 = d
+ aDistance.setValue(DISTANCE1)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ d += dStep
+assert (model.dof(aSketchFeature) == 3)
+
+#=========================================================================
+# Create a constraint to keep vertical distance between fixed and movable points
+#=========================================================================
+DISTANCE2 = 50.
+aSession.startOperation()
+aVDist2 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+aDistance = aVDist2.real("ConstraintValue")
+refattrA = aVDist2.refattr("ConstraintEntityA")
+refattrB = aVDist2.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setObject(anExtPoint.lastResult())
+refattrB.setAttr(aPoint1Coords)
+aDistance.setValue(DISTANCE2)
+aSession.finishOperation()
+assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+assert (model.dof(aSketchFeature) == 2)
+#=========================================================================
+# Change a distance value (check previous constraint is applied too)
+#=========================================================================
+d = DISTANCE2
+dStep = -5.
+while d >= -50.:
+ aSession.startOperation()
+ DISTANCE2 = d
+ aDistance.setValue(DISTANCE2)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ d += dStep
+assert (model.dof(aSketchFeature) == 2)
+
+#=========================================================================
+# Remove first distance
+#=========================================================================
+aStoredCoords = [aPoint2Coords.x(), aPoint2Coords.y()]
+aSession.startOperation()
+aDocument.removeFeature(aVDist1)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 3)
+aSession.startOperation()
+DISTANCE2 = 20.
+aDistance.setValue(DISTANCE2)
+aSession.finishOperation()
+assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+assert aPoint2Coords.x() == aStoredCoords[0] and aPoint2Coords.y() == aStoredCoords[1]
+
+#=========================================================================
+# Create line and set vertical distance between line boundaries
+#=========================================================================
+aSession.startOperation()
+aLine = aSketchFeature.addFeature("SketchLine")
+aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+aStartPoint.setValue(50., 0.)
+aEndPoint.setValue(100., 20.)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 7)
+
+DISTANCE3 = 50.
+aSession.startOperation()
+aVDist3 = aSketchFeature.addFeature("SketchConstraintDistanceVertical")
+aDistance = aVDist3.real("ConstraintValue")
+refattrA = aVDist3.refattr("ConstraintEntityA")
+refattrB = aVDist3.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+refattrA.setAttr(aStartPoint)
+refattrB.setAttr(aEndPoint)
+aDistance.setValue(DISTANCE3)
+aSession.finishOperation()
+assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
+assert (model.dof(aSketchFeature) == 6)
+#=========================================================================
+# Change a distance value
+#=========================================================================
+d = DISTANCE3
+dStep = -5.
+while d >= -50.:
+ aSession.startOperation()
+ DISTANCE3 = d
+ aDistance.setValue(DISTANCE3)
+ aSession.finishOperation()
+ assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ d += dStep
+assert (model.dof(aSketchFeature) == 6)
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+assert(model.checkPythonDump())
assert ((aLineBStartPoint.x(), aLineBStartPoint.y()) == (aLineAEndPoint.x(), aLineAEndPoint.y()))
assert ((aLineCStartPoint.x(), aLineCStartPoint.y()) == (aLineBEndPoint.x(), aLineBEndPoint.y()))
assert (model.dof(aSketchFeature) == 6)
+
+#=========================================================================
+# Create circle, fix it and check the circle is not moved
+#=========================================================================
+aCenter = [10., 10.]
+aRadius = 5.
+aSession.startOperation()
+aCircle = aSketchFeature.addFeature("SketchCircle")
+aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
+aCircleRadius = aCircle.real("circle_radius")
+aCircleCenter.setValue(aCenter[0], aCenter[1])
+aCircleRadius.setValue(aRadius)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 9)
+# fixed constraints
+aSession.startOperation()
+aRigidConstraint = aSketchFeature.addFeature("SketchConstraintRigid")
+aRigidConstraint.refattr("ConstraintEntityA").setObject(aCircle.lastResult())
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 6)
+# move center of circle
+aSession.startOperation()
+aCircleCenter.setValue(aCenter[0] + 1., aCenter[1] - 1.)
+aSession.finishOperation()
+assert (aCircleCenter.x() == aCenter[0] and aCircleCenter.y() == aCenter[1])
+assert (aCircleRadius.value() == aRadius)
+assert (model.dof(aSketchFeature) == 6)
+# change radius of circle
+aSession.startOperation()
+aCircleRadius.setValue(aRadius + 3.)
+aSession.finishOperation()
+assert (aCircleCenter.x() == aCenter[0] and aCircleCenter.y() == aCenter[1])
+assert (aCircleRadius.value() == aRadius)
+assert (model.dof(aSketchFeature) == 6)
+
+#=========================================================================
+# Remove Fixed constraint and check the circle can be moved
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aRigidConstraint)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 9)
+# move center of circle
+aCenter = [aCenter[0] + 1., aCenter[1] - 1.]
+aSession.startOperation()
+aCircleCenter.setValue(aCenter[0], aCenter[1])
+aSession.finishOperation()
+assert (aCircleCenter.x() == aCenter[0] and aCircleCenter.y() == aCenter[1])
+assert (aCircleRadius.value() == aRadius)
+assert (model.dof(aSketchFeature) == 9)
+# change radius of circle
+aRadius = aRadius + 3.
+aSession.startOperation()
+aCircleRadius.setValue(aRadius)
+aSession.finishOperation()
+assert (aCircleCenter.x() == aCenter[0] and aCircleCenter.y() == aCenter[1])
+assert (aCircleRadius.value() == aRadius)
+assert (model.dof(aSketchFeature) == 9)
+
+#=========================================================================
+# Create arc, fix it and check it is not moved
+#=========================================================================
+aCenter = [10., 10.]
+aStart = [5., 10.]
+aEnd = [10., 15.]
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcStart = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcEnd = geomDataAPI_Point2D(anArc.attribute("end_point"))
+anArcCenter.setValue(aCenter[0], aCenter[1])
+anArcStart.setValue(aStart[0], aStart[1])
+anArcEnd.setValue(aEnd[0], aEnd[1])
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 14)
+# fixed constraints
+aSession.startOperation()
+aRigidConstraint = aSketchFeature.addFeature("SketchConstraintRigid")
+aRigidConstraint.refattr("ConstraintEntityA").setObject(anArc.lastResult())
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 9)
+# move center of arc
+aSession.startOperation()
+anArcCenter.setValue(aCenter[0] + 1., aCenter[1] - 1.)
+aSession.finishOperation()
+assert (anArcCenter.x() == aCenter[0] and anArcCenter.y() == aCenter[1])
+assert (anArcStart.x() == aStart[0] and anArcStart.y() == aStart[1])
+assert (anArcEnd.x() == aEnd[0] and anArcEnd.y() == aEnd[1])
+assert (model.dof(aSketchFeature) == 9)
+# move start point of arc
+aSession.startOperation()
+anArcStart.setValue(aStart[0] + 1., aStart[1] - 1.)
+aSession.finishOperation()
+assert (anArcCenter.x() == aCenter[0] and anArcCenter.y() == aCenter[1])
+assert (anArcStart.x() == aStart[0] and anArcStart.y() == aStart[1])
+assert (anArcEnd.x() == aEnd[0] and anArcEnd.y() == aEnd[1])
+assert (model.dof(aSketchFeature) == 9)
+# move end point of arc
+aSession.startOperation()
+anArcEnd.setValue(aEnd[0] + 1., aEnd[1] - 1.)
+aSession.finishOperation()
+assert (anArcCenter.x() == aCenter[0] and anArcCenter.y() == aCenter[1])
+assert (anArcStart.x() == aStart[0] and anArcStart.y() == aStart[1])
+assert (anArcEnd.x() == aEnd[0] and anArcEnd.y() == aEnd[1])
+assert (model.dof(aSketchFeature) == 9)
+
+#=========================================================================
+# Remove Fixed constraint and check the arc can be moved
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aRigidConstraint)
+aSession.finishOperation()
+assert (model.dof(aSketchFeature) == 14)
+# move center of arc
+aCenter = [anArcCenter.x(), anArcCenter.y()]
+aSession.startOperation()
+anArcCenter.setValue(aCenter[0] + 1., aCenter[1] - 1.)
+aSession.finishOperation()
+assert (anArcCenter.x() != aCenter[0] or anArcCenter.y() != aCenter[1])
+assert (model.dof(aSketchFeature) == 14)
+# move start point of arc
+aStart = [anArcStart.x(), anArcStart.y()]
+aSession.startOperation()
+anArcStart.setValue(aStart[0] + 1., aStart[1] - 1.)
+aSession.finishOperation()
+assert (anArcStart.x() != aStart[0] or anArcStart.y() != aStart[1])
+assert (model.dof(aSketchFeature) == 14)
+# move end point of arc
+aEnd = [anArcEnd.x(), anArcEnd.y()]
+aSession.startOperation()
+anArcEnd.setValue(aEnd[0] + 1., aEnd[1] - 1.)
+aSession.finishOperation()
+assert (anArcEnd.x() != aEnd[0] or anArcEnd.y() != aEnd[1])
+assert (model.dof(aSketchFeature) == 14)
+
#=========================================================================
# End of test
#=========================================================================
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ TestConstraintHorizontalValidator.py
+ It tests validation of horizontal and vertical segments in H and V constraints to avoid
+ selection segments that already have one of these constraint"
+"""
+
+#=========================================================================
+# of the test
+#=========================================================================
+from salome.shaper import model
+from ModelAPI import *
+import math
+#=========================================================================
+# Creation of a part
+#=========================================================================
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 20, 40, 80)
+SketchLine_2 = Sketch_1.addLine(40, 80, 60, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+model.do()
+#=========================================================================
+# Checking that sketch and constraints become invalid when to one line
+# two horizontal/vertical constraints are applied in any combination
+#=========================================================================
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Sketch_1.feature()))
+assert(Sketch_1.feature().error() != '')
+#=========================================================================
+# Remove duplicated Vertical constraints
+#=========================================================================
+Part_1_doc.removeFeature(SketchConstraintVertical_1.feature())
+assert(aFactory.validate(Sketch_1.feature()))
+model.do()
+#=========================================================================
+# Checking that after excess constraints are removed or undone,
+# sketch becomes valid.
+#=========================================================================
+assert(aFactory.validate(Sketch_1.feature()))
+assert(Sketch_1.feature().error() == '')
+
+assert(model.checkPythonDump())
aFeature.real("x").setValue(0.)
aFeature.real("y").setValue(0.)
aFeature.real("z").setValue(0.)
+aFeature.string("creation_method").setValue("by_xyz")
anOriginName = aFeature.name()
aSession.finishOperation()
#=========================================================================
__updated__ = "2015-03-17"
-def distancePointLine(point, line):
- """
- subroutine to calculate distance between point and line
- result of calculated distance is has 10**-5 precision
- """
- aStartPoint = geomDataAPI_Point2D(line.attribute("StartPoint"))
- aEndPoint = geomDataAPI_Point2D(line.attribute("EndPoint"))
- # orthogonal direction
- aDirX = -(aEndPoint.y() - aStartPoint.y())
- aDirY = (aEndPoint.x() - aStartPoint.x())
- aLen = math.sqrt(aDirX**2 + aDirY**2)
- aDirX = aDirX / aLen
- aDirY = aDirY / aLen
- aVecX = point.x() - aStartPoint.x()
- aVecY = point.y() - aStartPoint.y()
- return round(math.fabs(aVecX * aDirX + aVecY * aDirY), 5)
-
def checkArcLineTangency(theArc, theLine):
"""
subroutine to check that the line is tangent to arc/circle
aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
aStartPnt = geomDataAPI_Point2D(theArc.attribute("start_point"))
aRadius = model.distancePointPoint(aStartPnt, aCenter)
- aDist = distancePointLine(aCenter, theLine)
+ aDist = model.distancePointLine(aCenter, theLine)
assert math.fabs(aDist - aRadius) < 2.e-5, "aDist = {0}, aRadius = {1}".format(aDist, aRadius)
def checkArcArcTangency(theArc1, theArc2):
subroutine to verify position of last arc in the sketch
"""
aLastArc = model.lastSubFeature(theSketch, "SketchArc")
- aCenterPnt = geomDataAPI_Point2D(aLastArc.attribute("center_point"))
- aStartPnt = geomDataAPI_Point2D(aLastArc.attribute("start_point"))
- aEndPnt = geomDataAPI_Point2D(aLastArc.attribute("end_point"))
- if len(theCenter):
- verifyPointCoordinates(aCenterPnt, theCenter[0], theCenter[1])
- if len(theStart):
- verifyPointCoordinates(aStartPnt, theStart[0], theStart[1])
- if len(theEnd):
- verifyPointCoordinates(aEndPnt, theEnd[0], theEnd[1])
- model.assertSketchArc(aLastArc)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertArc(aLastArc, theCenter, theStart, theEnd)
def verifyPointOnLine(thePoint, theLine):
- aDistance = distancePointLine(thePoint, theLine)
+ aDistance = model.distancePointLine(thePoint, theLine)
assert aDistance < TOLERANCE, "Point is not on Line, distance: {0}".format(aDistance)
def verifyPointOnCircle(thePoint, theCircular):
return
assert math.fabs(model.distancePointPoint(aCenterPoint, thePoint) - aRadius) < TOLERANCE
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
- aLineDir = aLineEnd.decreased(aLineStart)
- aLineLen = aLineEnd.distance(aLineStart)
- aPntDir = thePoint.pnt().xy().decreased(aLineStart)
- return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
-
aSession = ModelAPI_Session.get()
aDocument = aSession.moduleDocument()
aEnd.setValue(aLineStart[0], aLineStart[1])
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 8), "Number of subs {}".format(aSketchFeature.numberOfSubs())
-verifyPointCoordinates(aPointCoord, aPointCoordinates[0], aPointCoordinates[1])
+model.assertPoint(aPointCoord, aPointCoordinates)
verifyLastArc(aSketchFeature, [aPrevArcStart.x(), aPrevArcStart.y()], aPointCoordinates, [])
model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 12), "Number of subs {}".format(aSketchFeature.numberOfSubs())
# check connected features do not change their positions
-verifyPointCoordinates(aPrevArcCenter, aPrevArcCenterXY[0], aPrevArcCenterXY[1])
-verifyPointCoordinates(aPrevArcStart, aPrevArcStartXY[0], aPrevArcStartXY[1])
-verifyPointCoordinates(aPrevArcEnd, aPrevArcEndXY[0], aPrevArcEndXY[1])
-verifyPointCoordinates(aLineStartPoint, aLineStart[0], aLineStart[1])
-verifyPointCoordinates(aLineEndPoint, aLineEnd[0], aLineEnd[1])
+model.assertArc(aPrevArc, aPrevArcCenterXY, aPrevArcStartXY, aPrevArcEndXY)
+model.assertLine(aLine, aLineStart, aLineEnd)
# verify newly created arc
anArc = model.lastSubFeature(aSketchFeature, "SketchArc")
aCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
subroutine to verify position of last arc in the sketch
"""
aLastArc = model.lastSubFeature(theSketch, "SketchArc")
- aCenterPnt = geomDataAPI_Point2D(aLastArc.attribute("center_point"))
- aStartPnt = geomDataAPI_Point2D(aLastArc.attribute("start_point"))
- aEndPnt = geomDataAPI_Point2D(aLastArc.attribute("end_point"))
- if len(theCenter):
- verifyPointCoordinates(aCenterPnt, theCenter[0], theCenter[1])
- if len(theStart):
- verifyPointCoordinates(aStartPnt, theStart[0], theStart[1])
- if len(theEnd):
- verifyPointCoordinates(aEndPnt, theEnd[0], theEnd[1])
- model.assertSketchArc(aLastArc)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertArc(aLastArc, theCenter, theStart, theEnd)
def verifyTangent(theFeature1, theFeature2):
anArcs = []
aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
aRadius = model.distancePointPoint(aStart, aCenter)
- aDistCL = distancePointLine(aCenter, theLine)
+ aDistCL = model.distancePointLine(aCenter, theLine)
assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Arc and line do not tangent"
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
- aLineDir = aLineEnd.decreased(aLineStart)
- aLineLen = aLineEnd.distance(aLineStart)
- aPntDir = thePoint.pnt().xy().decreased(aLineStart)
- return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
-
def verifyPointOnLine(thePoint, theLine):
- aDistance = distancePointLine(thePoint, theLine)
+ aDistance = model.distancePointLine(thePoint, theLine)
assert aDistance < TOLERANCE, "Point is not on Line, distance: {0}".format(aDistance)
"""
aLastArc = model.lastSubFeature(theSketch, "SketchArc")
aCenter = geomDataAPI_Point2D(aLastArc.attribute("center_point"))
- verifyPointCoordinates(aCenter, theX, theY)
+ model.assertPoint(aCenter, [theX, theY])
aRadius = aLastArc.real("radius")
assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
-
def verifyPointOnArc(thePoint, theArc):
aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
aDistCP = model.distancePointPoint(aCenter, thePoint)
def verifyTangentArcLine(theArc, theLine):
aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
aRadius = theArc.real("radius").value()
- aDistCL = distancePointLine(aCenter, theLine)
+ aDistCL = model.distancePointLine(aCenter, theLine)
assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent"
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
- aLineDir = aLineEnd.decreased(aLineStart)
- aLineLen = aLineEnd.distance(aLineStart)
- aPntDir = thePoint.pnt().xy().decreased(aLineStart)
- return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
-
#=========================================================================
# Start of test
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 7)
# check the points do not change their positions
-verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
-verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1])
-verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
+model.assertPoint(aPrevCenter, aPrevCenterXY)
+model.assertPoint(aPointCoord, aPointCoodinates)
+model.assertPoint(aStartPnt, aLineStart)
# check newly created arc passes through the points
anArc = model.lastSubFeature(aSketchFeature, "SketchArc")
verifyPointOnArc(aPrevCenter, anArc)
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 9)
# check the points do not change their positions
-verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
-verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1])
-verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
+model.assertPoint(aPrevCenter, aPrevCenterXY)
+model.assertPoint(aPointCoord, aPointCoodinates)
+model.assertPoint(aStartPnt, aLineStart)
# check sub-features
model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 1)
subroutine to verify position of last arc in the sketch
"""
aLastArc = model.lastSubFeature(theSketch, "SketchArc")
- aCenterPnt = geomDataAPI_Point2D(aLastArc.attribute("center_point"))
- aStartPnt = geomDataAPI_Point2D(aLastArc.attribute("start_point"))
- aEndPnt = geomDataAPI_Point2D(aLastArc.attribute("end_point"))
- if len(theCenter):
- verifyPointCoordinates(aCenterPnt, theCenter[0], theCenter[1])
- if len(theStart):
- verifyPointCoordinates(aStartPnt, theStart[0], theStart[1])
- if len(theEnd):
- verifyPointCoordinates(aEndPnt, theEnd[0], theEnd[1])
- model.assertSketchArc(aLastArc)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertArc(aLastArc, theCenter, theStart, theEnd)
#=========================================================================
subroutine to verify position of last circle in the sketch
"""
aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
- aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
- verifyPointCoordinates(aCenter, theX, theY)
- aRadius = aLastCircle.real("circle_radius")
- assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.id(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertCircle(aLastCircle, [theX, theY], theR)
def verifyPointOnLine(thePoint, theLine):
- aDistance = distancePointLine(thePoint, theLine)
+ aDistance = model.distancePointLine(thePoint, theLine)
assert aDistance < TOLERANCE, "Point is not on Line, distance: {0}".format(aDistance)
def verifyTangentCircles(theCircle1, theCircle2):
aRDiff = math.fabs(aRadius1 - aRadius2)
assert math.fabs(aRSum - aDistCC) < TOLERANCE or math.fabs(aRDiff - aDistCC) < TOLERANCE, "Circles do not tangent"
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
- aLineDir = aLineEnd.decreased(aLineStart)
- aLineLen = aLineEnd.distance(aLineStart)
- aPntDir = thePoint.pnt().xy().decreased(aLineStart)
- return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
-
#=========================================================================
# Start of test
aRadius = model.distancePointPoint(aPrevCenter, aPointCoord)
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 6)
-verifyPointCoordinates(aPointCoord, aPointCoordinates[0], aPointCoordinates[1])
+model.assertPoint(aPointCoord, aPointCoordinates)
verifyLastCircle(aSketchFeature, aPointCoord.x(), aPointCoord.y(), aRadius)
model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 2)
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 10)
# check connected features do not change their positions
-verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
+model.assertPoint(aPrevCenter, aPrevCenterXY)
assert(aPrevCircle.real("circle_radius").value() == aPrevRadius)
-verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
-verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1])
+model.assertLine(aLine, aLineStart, aLineEnd)
# verify newly created circle
aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center"))
-verifyPointCoordinates(aCenter, anExpectedCenter[0], anExpectedCenter[1])
+model.assertPoint(aCenter, anExpectedCenter)
verifyPointOnLine(aCenter, aLine)
verifyTangentCircles(aCircle, aPrevCircle)
model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
subroutine to verify position of last circle in the sketch
"""
aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
- aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
- verifyPointCoordinates(aCenter, theX, theY)
- aRadius = aLastCircle.real("circle_radius")
- assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertCircle(aLastCircle, [theX, theY], theR)
def verifyPointOnCircle(thePoint, theCircle):
aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
def verifyTangentCircleLine(theCircle, theLine):
aCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center"))
aRadius = theCircle.real("circle_radius").value()
- aDistCL = distancePointLine(aCenter, theLine)
+ aDistCL = model.distancePointLine(aCenter, theLine)
assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent"
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy()
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy()
- aLineDir = aLineEnd.decreased(aLineStart)
- aLineLen = aLineEnd.distance(aLineStart)
- aPntDir = thePoint.pnt().xy().decreased(aLineStart)
- return math.fabs(aPntDir.cross(aLineDir) / aLineLen)
-
#=========================================================================
# Start of test
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 7)
# check the points do not change their positions
-verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
-verifyPointCoordinates(aPointCoord, aPointCoordinates[0], aPointCoordinates[1])
-verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
+model.assertPoint(aPrevCenter, aPrevCenterXY)
+model.assertPoint(aPointCoord, aPointCoordinates)
+model.assertPoint(aStartPnt, aLineStart)
# check newly created circle passes through the points
aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
verifyPointOnCircle(aPrevCenter, aCircle)
aSession.finishOperation()
assert (aSketchFeature.numberOfSubs() == 12)
# check the tangent entities do not change their positions
-verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1])
+model.assertPoint(aPrevCenter, aPrevCenterXY)
assert (aPrevCircle.real("circle_radius").value() == aPrevCircleRadius)
-verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1])
-verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1])
-verifyPointCoordinates(anArcCenterPnt, anArcCenter[0], anArcCenter[1])
-verifyPointCoordinates(anArcStartPnt, anArcStart[0], anArcStart[1])
-verifyPointCoordinates(anArcEndPnt, anArcEnd[0], anArcEnd[1])
+model.assertLine(aLine, aLineStart, aLineEnd)
+model.assertArc(anArc, anArcCenter, anArcStart, anArcEnd)
# check newly created circle passes through the points
aCircle = model.lastSubFeature(aSketchFeature, "SketchCircle")
verifyTangentCircles(aCircle, aPrevCircle)
subroutine to verify position of last circle in the sketch
"""
aLastCircle = model.lastSubFeature(theSketch, "SketchCircle")
- aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center"))
- verifyPointCoordinates(aCenter, theX, theY)
- aRadius = aLastCircle.real("circle_radius")
- assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR)
-
-def verifyPointCoordinates(thePoint, theX, theY):
- assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY)
+ model.assertCircle(aLastCircle, [theX, theY], theR)
#=========================================================================
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+widthParam = model.addParameter(partSet, "w", "200")
+distParam = model.addParameter(partSet, "d", "30")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100)
+[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines()
+Origin = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Origin.result())
+Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w")
+Point_1 = Sketch_1.addPoint(230, 40)
+Sketch_1.setSignedDistance(Point_1.result(), SketchAPI_Line(Line_4).result(), "d")
+Point_2 = Sketch_1.addPoint(230, 80)
+Sketch_1.setUnsignedDistance(Point_2.result(), SketchAPI_Line(Line_4).result(), "d")
+model.do()
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+line = model.toSketchFeature(Line_4)
+signedDist1 = model.signedDistancePointLine(Point_1, line)
+signedDist2 = model.signedDistancePointLine(Point_2, line)
+
+# change rectangle width and check distances
+widthParam.setValue(2000)
+model.do()
+curDist = model.signedDistancePointLine(Point_1, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(Point_2, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+# revert rectangle width and check distances again
+widthParam.setValue(200)
+model.do()
+curDist = model.signedDistancePointLine(Point_1, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(Point_2, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+model.end()
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+widthParam = model.addParameter(partSet, "w", "200")
+distParam = model.addParameter(partSet, "d", "30")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100)
+[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines()
+Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result())
+Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w")
+Circle_1 = Sketch_1.addCircle(230, 40, 20)
+Sketch_1.setSignedDistance(Circle_1.center(), SketchAPI_Line(Line_4).result(), "d")
+Circle_2 = Sketch_1.addCircle(230, 80, 20)
+Sketch_1.setUnsignedDistance(Circle_2.center(), SketchAPI_Line(Line_4).result(), "d")
+model.do()
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+center1 = Circle_1.center()
+center2 = Circle_2.center()
+line = model.toSketchFeature(Line_4)
+signedDist1 = model.signedDistancePointLine(center1, line)
+signedDist2 = model.signedDistancePointLine(center2, line)
+
+# change rectangle width and check distances
+widthParam.setValue(2000)
+model.do()
+curDist = model.signedDistancePointLine(center1, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(center2, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+# revert rectangle width and check distances again
+widthParam.setValue(200)
+model.do()
+curDist = model.signedDistancePointLine(center1, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(center2, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+model.end()
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+widthParam = model.addParameter(partSet, "w", "200")
+distParam = model.addParameter(partSet, "d", "30")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100)
+[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines()
+Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result())
+Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w")
+Line_5 = Sketch_1.addLine(230, 40, 230, 80)
+Sketch_1.setSignedDistance(Line_5.startPoint(), SketchAPI_Line(Line_4).result(), "d")
+Sketch_1.setUnsignedDistance(Line_5.endPoint(), SketchAPI_Line(Line_4).result(), "d")
+model.do()
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+start = Line_5.startPoint()
+end = Line_5.endPoint()
+line = model.toSketchFeature(Line_4)
+signedDist1 = model.signedDistancePointLine(start, line)
+signedDist2 = model.signedDistancePointLine(end, line)
+
+# change rectangle width and check distances
+widthParam.setValue(2000)
+model.do()
+curDist = model.signedDistancePointLine(start, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(end, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+# revert rectangle width and check distances again
+widthParam.setValue(200)
+model.do()
+curDist = model.signedDistancePointLine(start, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(end, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+model.end()
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+widthParam = model.addParameter(partSet, "w", "200")
+distParam = model.addParameter(partSet, "d", "30")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100)
+[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines()
+Point_1 = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Point_1.result())
+Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w")
+Arc_1 = Sketch_1.addArc(250, 60, 230, 40, 230, 80, False)
+Sketch_1.setSignedDistance(Arc_1.startPoint(), SketchAPI_Line(Line_4).result(), "d")
+Sketch_1.setUnsignedDistance(Arc_1.endPoint(), SketchAPI_Line(Line_4).result(), "d")
+model.do()
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+start = Arc_1.startPoint()
+end = Arc_1.endPoint()
+line = model.toSketchFeature(Line_4)
+signedDist1 = model.signedDistancePointLine(start, line)
+signedDist2 = model.signedDistancePointLine(end, line)
+
+# change rectangle width and check distances
+widthParam.setValue(1000)
+model.do()
+curDist = model.signedDistancePointLine(start, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(end, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+model.assertArcValidity(Arc_1)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+# revert rectangle width and check distances again
+widthParam.setValue(200)
+model.do()
+curDist = model.signedDistancePointLine(start, line)
+assert(math.fabs(signedDist1 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist1, curDist)
+curDist = model.signedDistancePointLine(end, line)
+assert(math.fabs(math.fabs(signedDist2) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist2, -curDist)
+model.assertArcValidity(Arc_1)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+model.end()
--- /dev/null
+## Copyright (C) 2017 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
+from SketchAPI import *
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+widthParam = model.addParameter(partSet, "w", "200")
+distParam = model.addParameter(partSet, "d", "30")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+Rectangle_1 = Sketch_1.addRectangle(0, 0, 200, 100)
+[Line_1, Line_2, Line_3, Line_4] = Rectangle_1.lines()
+Origin = Sketch_1.addPoint(model.selection("VERTEX", "Origin"))
+Sketch_1.setCoincident(SketchAPI_Line(Line_1).endPoint(), Origin.result())
+Sketch_1.setLength(SketchAPI_Line(Line_1).result(), "w")
+Point_1 = Sketch_1.addPoint(230, 40)
+Sketch_1.setSignedDistance(Point_1.result(), SketchAPI_Line(Line_4).result(), "d")
+Point_2 = Sketch_1.addPoint(230, 80)
+Sketch_1.setUnsignedDistance(Point_2.result(), SketchAPI_Line(Line_4).result(), "d")
+Line_5 = Sketch_1.addLine(260, 0, 260, 100)
+Sketch_1.setSignedDistance(Point_1.result(), Line_5.result(), "d")
+Sketch_1.setUnsignedDistance(Point_2.result(), Line_5.result(), "d")
+model.do()
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+line4 = model.toSketchFeature(Line_4)
+line5 = model.toSketchFeature(Line_5)
+signedDist14 = model.signedDistancePointLine(Point_1, line4)
+signedDist15 = model.signedDistancePointLine(Point_1, line5)
+signedDist24 = model.signedDistancePointLine(Point_2, line4)
+signedDist25 = model.signedDistancePointLine(Point_2, line5)
+
+# change rectangle width and check distances
+widthParam.setValue(2000)
+model.do()
+curDist = model.signedDistancePointLine(Point_1, line4)
+assert(math.fabs(signedDist14 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist14, curDist)
+curDist = model.signedDistancePointLine(Point_2, line4)
+assert(math.fabs(math.fabs(signedDist24) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist24, -curDist)
+curDist = model.signedDistancePointLine(Point_1, line5)
+assert(math.fabs(signedDist15 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist15, curDist)
+curDist = model.signedDistancePointLine(Point_2, line5)
+assert(math.fabs(math.fabs(signedDist25) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist25, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+# revert rectangle width and check distances again
+widthParam.setValue(200)
+model.do()
+curDist = model.signedDistancePointLine(Point_1, line4)
+assert(math.fabs(signedDist14 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist14, curDist)
+curDist = model.signedDistancePointLine(Point_2, line4)
+assert(math.fabs(math.fabs(signedDist24) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist24, -curDist)
+curDist = model.signedDistancePointLine(Point_1, line5)
+assert(math.fabs(signedDist15 - curDist) < TOLERANCE), "Expected {}, actual {}".format(signedDist15, curDist)
+curDist = model.signedDistancePointLine(Point_2, line5)
+assert(math.fabs(math.fabs(signedDist25) - math.fabs(curDist)) < TOLERANCE), "Expected {}, actual {}".format(signedDist25, -curDist)
+assert Sketch_1.solverError().value() == "", "FAILED: Sketch should NOT report over-constrained situation"
+
+model.end()
def checkArcLineSmoothness(theArc, theLine):
aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
- aDistance = distancePointLine(aCenter, theLine)
+ aDistance = model.distancePointLine(aCenter, theLine)
aRadius = arcRadius(theArc)
assert(math.fabs(aRadius - aDistance) < TOLERANCE)
aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
return model.distancePointPoint(aCenter, aStart)
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
- aLength = model.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
-
#=========================================================================
# Initialization of the test
def isArcLineSmooth(theArc, theLine, theTolerance):
aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
- aDistance = distancePointLine(aCenter, theLine)
+ aDistance = model.distancePointLine(aCenter, theLine)
aRadius = arcRadius(theArc)
return math.fabs(aRadius - aDistance) < theTolerance
aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
return model.distancePointPoint(aCenter, aStart)
-def distancePointLine(thePoint, theLine):
- aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
- aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
- aLength = model.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
-
class TestFilletInteracting(unittest.TestCase):
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ Test movement of the sketch arc of circle
+"""
+
+import unittest
+from GeomDataAPI import geomDataAPI_Point2D
+from salome.shaper import model
+
+__updated__ = "2017-05-11"
+
+class TestMoveArc(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = [50., 50.]
+ self.myStart = [70., 50.]
+ self.myEnd = [50., 70.]
+ self.myArc = self.mySketch.addArc(self.myCenter[0], self.myCenter[1], self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1], False)
+ self.myDOF = 5
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ model.assertArcValidity(self.myArc)
+ self.checkDOF()
+ model.end()
+ assert(model.checkPythonDump())
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointCoordinates(self, thePoint, theCoordinates):
+ self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+ self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+
+ def checkPointOnArc(self, theCoordinates):
+ distPC = model.distancePointPoint(self.myArc.center(), theCoordinates)
+ radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint())
+ self.assertAlmostEqual(distPC, radius)
+
+ def checkArcRadius(self):
+ radius = model.distancePointPoint(self.myArc.center(), self.myArc.startPoint())
+ self.assertAlmostEqual(radius, self.myRadius)
+
+ def fixArcRadius(self):
+ self.myRadius = 20.
+ self.mySketch.setRadius(self.myArc.results()[1], self.myRadius)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ def fixPoint(self, thePoint):
+ self.mySketch.setFixed(thePoint)
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+ def fixArc(self):
+ self.mySketch.setFixed(self.myArc.results()[1])
+ self.myDOF -= 5
+ model.do()
+ self.checkDOF()
+
+
+ def test_move_center_of_free_arc(self):
+ """ Test 1. Movement of center of a free arc
+ """
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), newPosition)
+
+ def test_move_start_of_free_arc(self):
+ """ Test 2. Movement of start point of a free arc
+ """
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), newPosition)
+
+ def test_move_end_of_free_arc(self):
+ """ Test 3. Movement of end point of a free arc
+ """
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.endPoint(), newPosition)
+
+ def test_move_free_arc(self):
+ """ Test 4. Movement of a free arc dragging the edge
+ """
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointOnArc(newPosition)
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+
+ def test_move_center_of_arc_fixed_center(self):
+ """ Test 5. Movement of center of the arc with fixed center (nothing should be changed)
+ """
+ self.fixPoint(self.myArc.center())
+
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+
+ def test_move_start_of_arc_fixed_center(self):
+ """ Test 6. Movement of start point of the arc with fixed center
+ """
+ self.fixPoint(self.myArc.center())
+
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), newPosition)
+
+ def test_move_end_of_arc_fixed_center(self):
+ """ Test 7. Movement of end point of the arc with fixed center
+ """
+ self.fixPoint(self.myArc.center())
+
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.endPoint(), newPosition)
+
+ def test_move_arc_fixed_center(self):
+ """ Test 8. Movement of the arc with fixed center dragging the edge
+ """
+ self.fixPoint(self.myArc.center())
+
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointOnArc(newPosition)
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+
+ def test_move_center_of_arc_fixed_start(self):
+ """ Test 9. Movement of center of the arc with fixed start point
+ """
+ self.fixPoint(self.myArc.startPoint())
+
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), newPosition)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+
+ def test_move_start_of_arc_fixed_start(self):
+ """ Test 10. Movement of start point of the arc with fixed start point (nothing should be changed)
+ """
+ self.fixPoint(self.myArc.startPoint())
+
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_end_of_arc_fixed_start(self):
+ """ Test 11. Movement of end point of the arc with fixed start point
+ """
+ self.fixPoint(self.myArc.startPoint())
+
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+ self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+
+ def test_move_arc_fixed_start(self):
+ """ Test 12. Movement of the arc with fixed start point dragging the edge
+ """
+ self.fixPoint(self.myArc.startPoint())
+
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+ self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+
+ def test_move_center_of_arc_fixed_end(self):
+ """ Test 13. Movement of center of the arc with fixed end point
+ """
+ self.fixPoint(self.myArc.endPoint())
+
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), newPosition)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_start_of_arc_fixed_end(self):
+ """ Test 14. Movement of start point of the arc with fixed end point
+ """
+ self.fixPoint(self.myArc.endPoint())
+
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+ self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+ self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+
+ def test_move_end_of_arc_fixed_end(self):
+ """ Test 15. Movement of end point of the arc with fixed end point (nothing should be changed)
+ """
+ self.fixPoint(self.myArc.endPoint())
+
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_arc_fixed_end(self):
+ """ Test 16. Movement of the arc with fixed end point dragging the edge
+ """
+ self.fixPoint(self.myArc.endPoint())
+
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+ self.assertNotEqual(self.myArc.center().x(), self.myCenter[0])
+ self.assertNotEqual(self.myArc.center().y(), self.myCenter[1])
+
+ def test_move_center_of_arc_fixed_radius(self):
+ """ Test 17. Movement of center of the arc with fixed radius
+ """
+ self.fixArcRadius()
+
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), newPosition)
+ self.checkArcRadius()
+
+ def test_move_start_of_arc_fixed_radius(self):
+ """ Test 18. Movement of start point of the arc with fixed radius
+ """
+ self.fixArcRadius()
+
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkArcRadius()
+
+ def test_move_end_of_arc_fixed_radius(self):
+ """ Test 19. Movement of end point of the arc with fixed radius
+ """
+ self.fixArcRadius()
+
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkArcRadius()
+
+ def test_move_arc_fixed_radius(self):
+ """ Test 20. Movement of the arc with fixed radius dragging the edge
+ """
+ self.fixArcRadius()
+
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkArcRadius()
+
+ def test_move_center_of_fixed_arc(self):
+ """ Test 21. Movement of center of fully fixed arc (nothing should be changed)
+ """
+ self.fixArc()
+
+ newPosition = [self.myCenter[0] + 10., self.myCenter[1] - 15.]
+ self.mySketch.move(self.myArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_start_of_fixed_arc(self):
+ """ Test 22. Movement of start point of fully fixed arc (nothing should be changed)
+ """
+ self.fixArc()
+
+ newPosition = [self.myStart[0] - 10., self.myStart[1] + 5.]
+ self.mySketch.move(self.myArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_end_of_fixed_arc(self):
+ """ Test 23. Movement of end point of fully fixed arc (nothing should be changed)
+ """
+ self.fixArc()
+
+ newPosition = [self.myEnd[0] + 10., self.myEnd[1] + 5.]
+ self.mySketch.move(self.myArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+ def test_move_fixed_arc(self):
+ """ Test 24. Movement of fully fixed arc (nothing should be changed)
+ """
+ self.fixArc()
+
+ newPosition = [100., 80.]
+ self.mySketch.move(self.myArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myArc.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myArc.endPoint(), self.myEnd)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ Test movement of the sketch circle
+"""
+
+import unittest
+from GeomDataAPI import geomDataAPI_Point2D
+from salome.shaper import model
+
+__updated__ = "2017-05-11"
+
+class TestMoveCircle(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = [70., 50.]
+ self.myRadius = 20.
+ self.myCircle = self.mySketch.addCircle(self.myCenter[0], self.myCenter[1], self.myRadius)
+ self.myDOF = 3
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+ assert(model.checkPythonDump())
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointCoordinates(self, thePoint, theCoordinates):
+ self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+ self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+
+ def checkPointOnCircle(self, theCoordinates):
+ self.assertAlmostEqual(model.distancePointPoint(self.myCircle.center(), theCoordinates), self.myCircle.radius().value())
+
+ def fixCircleRadius(self):
+ self.mySketch.setRadius(self.myCircle.results()[1], self.myRadius)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ def fixCircleCenter(self):
+ self.mySketch.setFixed(self.myCircle.center())
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+
+ def test_move_center_free_circle(self):
+ """ Test 1. Movement of central point of a free circle
+ """
+ newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myCircle.center(), newPosition)
+ self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+
+ def test_move_free_circle(self):
+ """ Test 2. Movement of a free circle dragging the edge
+ """
+ newPosition = [120., 90.]
+ self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+ self.checkPointOnCircle(newPosition)
+ self.assertNotEqual(self.myCircle.radius().value(), self.myRadius)
+
+ def test_move_center_circle_fixed_radius(self):
+ """ Test 3. Movement of central point of a circle with fixed radius
+ """
+ self.fixCircleRadius()
+
+ newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myCircle.center(), newPosition)
+ self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+
+ def test_move_circle_fixed_radius(self):
+ """ Test 4. Movement of a circle with fixed radius
+ """
+ self.fixCircleRadius()
+
+ newPosition = [120., 90.]
+ self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+ self.assertNotEqual(self.myCircle.center().x(), self.myCenter[0])
+ self.assertNotEqual(self.myCircle.center().y(), self.myCenter[1])
+
+ def test_move_center_circle_fixed_center(self):
+ """ Test 5. Movement of central point of a circle with fixed center (nothing should be changed)
+ """
+ self.fixCircleCenter()
+
+ newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myCircle.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+ self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+
+ def test_move_circle_fixed_center(self):
+ """ Test 6. Movement of a circle with fixed center
+ """
+ self.fixCircleCenter()
+
+ newPosition = [120., 90.]
+ self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointOnCircle(newPosition)
+ self.assertNotEqual(self.myCircle.radius().value(), self.myRadius)
+
+ def test_move_fixed_circle(self):
+ """ Test 7. Trying to move fully fixed circle
+ """
+ self.fixCircleCenter()
+ self.fixCircleRadius()
+
+ newPosition = [120., 90.]
+ self.mySketch.move(self.myCircle.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myCircle.center(), self.myCenter)
+ self.assertAlmostEqual(self.myCircle.radius().value(), self.myRadius)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ Test movement of the sketch line
+"""
+
+import unittest
+from GeomDataAPI import geomDataAPI_Point2D
+from salome.shaper import model
+
+__updated__ = "2017-05-11"
+
+class TestMoveLine(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myStart = [70., 50.]
+ self.myEnd = [100., 20.]
+ self.myLine = self.mySketch.addLine(self.myStart[0], self.myStart[1], self.myEnd[0], self.myEnd[1])
+ self.myDOF = 4
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+ assert(model.checkPythonDump())
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointCoordinates(self, thePoint, theCoordinates):
+ self.assertAlmostEqual(thePoint.x(), theCoordinates[0])
+ self.assertAlmostEqual(thePoint.y(), theCoordinates[1])
+
+ def checkPointOnLine(self, theCoordinates):
+ self.assertAlmostEqual(model.distancePointLine(theCoordinates, self.myLine), 0.)
+
+ def test_move_start_of_free_line(self):
+ """ Test 1. Movement of start point of a free line
+ """
+ newPosition = [self.myStart[0] + 20., self.myStart[1] + 10.]
+ self.mySketch.move(self.myLine.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myLine.startPoint(), newPosition)
+ self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+
+ def test_move_end_of_free_line(self):
+ """ Test 2. Movement of end point of a free line
+ """
+ newPosition = [self.myEnd[0] + 20., self.myEnd[1] + 10.]
+ self.mySketch.move(self.myLine.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myLine.endPoint(), newPosition)
+
+ def test_move_free_line(self):
+ """ Test 3. Movement of free line
+ """
+ diff = [self.myEnd[0] - self.myStart[0], self.myEnd[1] - self.myStart[1]]
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointOnLine(newPosition)
+
+ # additionally check the line keeps geometry (relative positions of extremities)
+ startPoint = self.myLine.startPoint()
+ endPoint = [startPoint.x() + diff[0], startPoint.y() + diff[1]]
+ self.checkPointCoordinates(self.myLine.endPoint(), endPoint)
+
+ def test_move_line_start_fixed(self):
+ """ Test 4. Movement of a line, which start point is fixed
+ """
+ fixed = self.mySketch.setFixed(self.myLine.startPoint())
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+ self.assertNotEqual(self.myLine.endPoint().x(), self.myEnd[0])
+ self.assertNotEqual(self.myLine.endPoint().y(), self.myEnd[1])
+
+ def test_move_line_end_fixed(self):
+ """ Test 5. Movement of a line, which end point is fixed
+ """
+ fixed = self.mySketch.setFixed(self.myLine.endPoint())
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.assertNotEqual(self.myLine.startPoint().x(), self.myStart[0])
+ self.assertNotEqual(self.myLine.startPoint().y(), self.myStart[1])
+ self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+
+ def test_move_line_fully_fixed(self):
+ """ Test 6. Movement of fully fixed line (should not change its coordinates)
+ """
+ fixed = self.mySketch.setFixed(self.myLine.defaultResult())
+ self.myDOF -= 4
+ model.do()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myLine.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myLine.startPoint(), self.myStart)
+ self.checkPointCoordinates(self.myLine.endPoint(), self.myEnd)
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ Test movement of the sketch point
+"""
+
+import unittest
+from GeomDataAPI import geomDataAPI_Point2D
+from salome.shaper import model
+
+__updated__ = "2017-05-11"
+
+class TestMovePoint(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myOrigin = self.mySketch.addPoint(model.selection("VERTEX", "Origin"))
+ self.myPoint = self.mySketch.addPoint(70, 50)
+ self.myPointCoordinates = geomDataAPI_Point2D(self.myPoint.coordinates())
+ self.myDOF = 2
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+ assert(model.checkPythonDump())
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def test_move_free_point(self):
+ """ Test 1. Movement of free point
+ """
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+ model.do()
+ self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0])
+ self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1])
+
+ def test_move_fixed_x(self):
+ """ Test 2. Movement of partially fixed point (fixed x coordinate)
+ """
+ DISTANCE = 50.
+ horizDistance = self.mySketch.setHorizontalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+ model.do()
+ self.assertAlmostEqual(self.myPointCoordinates.x(), DISTANCE)
+ self.assertAlmostEqual(self.myPointCoordinates.y(), newPosition[1])
+
+ def test_move_fixed_y(self):
+ """ Test 3. Movement of partially fixed point (fixed y coordinate)
+ """
+ DISTANCE = 50.
+ vertDistance = self.mySketch.setVerticalDistance(self.myOrigin.result(), self.myPoint.coordinates(), DISTANCE)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+ model.do()
+ self.assertAlmostEqual(self.myPointCoordinates.x(), newPosition[0])
+ self.assertAlmostEqual(self.myPointCoordinates.y(), DISTANCE)
+
+ def test_move_fully_fixed(self):
+ """ Test 4. Movement of fully fixed point (should not be changed)
+ """
+ coord = [self.myPointCoordinates.x(), self.myPointCoordinates.y()]
+
+ fixed = self.mySketch.setFixed(self.myPoint.result())
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+ newPosition = [100., 100.]
+ self.mySketch.move(self.myPoint, newPosition[0], newPosition[1])
+ model.do()
+ self.assertAlmostEqual(self.myPointCoordinates.x(), coord[0])
+ self.assertAlmostEqual(self.myPointCoordinates.y(), coord[1])
+
+
+if __name__ == '__main__':
+ unittest.main()
--- /dev/null
+## Copyright (C) 2017 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>
+##
+
+"""
+ Test moving the entities in the complex sketch by the example of a clamp
+"""
+
+from salome.shaper import model
+from SketchAPI import *
+from GeomAPI import *
+import math
+
+TOLERANCE = 1.e-7
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Create sketch representing main part of clamp
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(20, 165, 175, 165)
+SketchLine_2 = Sketch_1.addLine(175, 165, 175, 120)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(175, 120, 80, 20)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(80, 20, 20, 20)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(20, 20, 20, 165)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.endPoint())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 155)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchLine_1.result())
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_4.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_5.result())
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 45)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_4.startPoint(), SketchLine_1.result(), 145)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_4.startPoint(), SketchLine_3.startPoint(), 95)
+SketchPoint_1 = Sketch_1.addPoint(model.selection("VERTEX", "PartSet/Origin"))
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchPoint_1.coordinates(), SketchLine_5.endPoint(), 165)
+model.do()
+
+# =============================================================================
+# Test 1. Create fillet and move fillet arc
+# =============================================================================
+Sketch_1.setFillet(SketchLine_5.startPoint())
+SketchArc_1 = SketchAPI_Arc(model.lastSubFeature(Sketch_1, "SketchArc"))
+model.do()
+anArcCenter = [SketchArc_1.center().x(), SketchArc_1.center().y()]
+anArcStart = [SketchArc_1.startPoint().x(), SketchArc_1.startPoint().y()]
+anArcEnd = [SketchArc_1.endPoint().x(), SketchArc_1.endPoint().y()]
+# move arc dragging center
+delta = [1., 1.]
+for i in range(1, 10):
+ anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+ Sketch_1.move(SketchArc_1.center(), anArcCenter[0], anArcCenter[1])
+ model.do()
+ model.assertArcValidity(SketchArc_1)
+ model.assertPoint(SketchArc_1.center(), anArcCenter)
+ assert(SketchArc_1.startPoint().x() == anArcStart[0])
+ assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+ if i == 5:
+ delta = [-1., -1.]
+# move arc dragging start point
+delta = [1., 1.]
+aPosition = anArcStart
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchArc_1.startPoint(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertArcValidity(SketchArc_1)
+ assert(SketchArc_1.startPoint().x() == anArcStart[0])
+ assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+ if i == 5:
+ delta = [-1., -1.]
+# move arc dragging end point
+delta = [1., 1.]
+aPosition = anArcEnd
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchArc_1.endPoint(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertArcValidity(SketchArc_1)
+ assert(SketchArc_1.startPoint().x() == anArcStart[0])
+ assert(SketchArc_1.endPoint().y() == anArcEnd[1])
+ if i == 5:
+ delta = [-1., -1.]
+
+# =============================================================================
+# Test 2. Create circle and move it near its potential position
+# =============================================================================
+aCircleCenter = [0, 0]
+aCircleRadius = 5
+SketchCircle_1 = Sketch_1.addCircle(aCircleCenter[0], aCircleCenter[1], aCircleRadius)
+model.do()
+# move center
+delta = [3., 2.]
+for i in range(1, 15):
+ aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.center(), aCircleCenter[0], aCircleCenter[1])
+ model.do()
+ model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+ assert(SketchCircle_1.radius().value() == aCircleRadius)
+# move circle by dragging edge
+aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+delta = [1., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+ assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+
+# =============================================================================
+# Test 3. Constrain center of circle and move it again
+# =============================================================================
+SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchCircle_1.center(), SketchArc_1.startPoint(), -30)
+model.do()
+# move center
+delta = [1., 1.]
+aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+aPosition = aCircleCenter
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1])
+ model.do()
+ assert(SketchCircle_1.center().x() == aCircleCenter[0])
+ if i == 5:
+ delta = [-1., -1.]
+# move circle by dragging edge
+aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+delta = [1., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+ assert(math.fabs(SketchCircle_1.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+# set radius of the circle
+aCircleRadius = 17.5
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], aCircleRadius)
+model.do()
+# move center
+delta = [1., 1.]
+aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+aPosition = aCircleCenter
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.center(), aPosition[0], aPosition[1])
+ model.do()
+ assert(SketchCircle_1.center().x() == aCircleCenter[0])
+ assert(SketchCircle_1.radius().value() == aCircleRadius)
+ if i == 5:
+ delta = [-1., -1.]
+# move circle by dragging edge
+aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+delta = [1., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ assert(SketchCircle_1.center().x() == aCircleCenter[0])
+ assert(SketchCircle_1.radius().value() == aCircleRadius)
+
+# =============================================================================
+# Test 4. Set centers of circle and arc coincident and move circle
+# =============================================================================
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchArc_1.center())
+model.do()
+assert(model.dof(Sketch_1) == 0)
+# move circle
+aCircleCenter = [SketchCircle_1.center().x(), SketchCircle_1.center().y()]
+aPosition = [aCircleCenter[0], aCircleCenter[1] + aCircleRadius]
+delta = [0., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_1.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertPoint(SketchCircle_1.center(), aCircleCenter)
+ assert(SketchCircle_1.radius().value() == aCircleRadius)
+assert(model.dof(Sketch_1) == 0)
+
+# Extrude main part of clamp
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchArc_1_2f-SketchCircle_1_2r")], model.selection(), 10, 0)
+model.do()
+
+
+# Create sketch representing orthogonal part of clamp
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchRectangle_1 = Sketch_2.addRectangle(20, 0, 100, 50)
+[SketchLine_6, SketchLine_7, SketchLine_8, SketchLine_9] = SketchRectangle_1.lines()
+SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"))
+SketchLine_10 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_7).startPoint(), SketchAPI_Line(SketchLine_10).startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_8.result(), SketchLine_10.result())
+SketchConstraintLength_3 = Sketch_2.setLength(SketchLine_7.result(), 80)
+model.do()
+assert(model.dof(Sketch_2) == 0)
+
+# Create auxiliary lines for further holes
+SketchLine_11 = Sketch_2.addLine(20, 10, 175, 10)
+SketchLine_11.setAuxiliary(True)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_11.startPoint(), SketchLine_7.result())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_9.result())
+SketchConstraintParallel_2 = Sketch_2.setParallel(SketchLine_11.result(), SketchLine_8.result())
+SketchLine_12 = Sketch_2.addLine(150, 0, 150, 80)
+SketchLine_12.setAuxiliary(True)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_12.startPoint(), SketchLine_6.result())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_8.result())
+SketchConstraintPerpendicular_2 = Sketch_2.setPerpendicular(SketchLine_11.result(), SketchLine_12.result())
+model.do()
+assert(model.dof(Sketch_2) == 2)
+
+# =============================================================================
+# Test 5. Create circular hole and move it
+# =============================================================================
+SketchCircle_2 = Sketch_2.addCircle(50, 10, 10)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchCircle_2.center(), SketchLine_11.result())
+model.do()
+# move center
+delta = [2., 1.]
+aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+aCircleRadius = SketchCircle_2.radius().value()
+for i in range(1, 10):
+ aCircleCenter = [aCircleCenter[0] + delta[0], aCircleCenter[1] + delta[1]]
+ Sketch_2.move(SketchCircle_2.center(), aCircleCenter[0], aCircleCenter[1])
+ model.do()
+ model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+ assert(aCircleRadius == SketchCircle_2.radius().value())
+# move circle by dragging edge
+aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+aPosition = [aCircleCenter[0] + aCircleRadius, aCircleCenter[1]]
+delta = [0., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_1.move(SketchCircle_2.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+ assert(math.fabs(SketchCircle_2.radius().value() - model.distancePointPoint(aPosition, aCircleCenter)) < TOLERANCE)
+
+SketchConstraintDistanceHorizontal_4 = Sketch_2.setHorizontalDistance(SketchLine_11.startPoint(), SketchCircle_2.center(), 21.5)
+model.do()
+assert(model.dof(Sketch_2) == 3)
+
+# =============================================================================
+# Test 6. Create oval hole and move it
+# =============================================================================
+anArcRadius = 5
+anArcCenter = [SketchLine_11.endPoint().x() + anArcRadius, SketchCircle_2.center().y()]
+SketchArc_2 = Sketch_2.addArc(anArcCenter[0], anArcCenter[1], anArcCenter[0], anArcCenter[1] + anArcRadius, anArcCenter[0], anArcCenter[1] - anArcRadius, True)
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchArc_2.center(), SketchLine_11.result())
+SketchLine_13 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] + anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] + anArcRadius)
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchArc_2.startPoint(), SketchLine_13.startPoint())
+SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_12.result())
+SketchConstraintPerpendicular_3 = Sketch_2.setPerpendicular(SketchLine_13.result(), SketchLine_12.result())
+SketchLine_14 = Sketch_2.addLine(anArcCenter[0], anArcCenter[1] - anArcRadius, SketchLine_12.startPoint().x(), anArcCenter[1] - anArcRadius)
+SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_12.result())
+SketchConstraintPerpendicular_4 = Sketch_2.setPerpendicular(SketchLine_14.result(), SketchLine_12.result())
+SketchConstraintTangent_1 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_13.result())
+SketchConstraintTangent_2 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_14.result())
+model.do()
+assert(model.dof(Sketch_2) == 5)
+# move center of arc
+delta = [-2., 1.]
+anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+for i in range(1, 10):
+ anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+ Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1])
+ model.do()
+ model.assertArc(SketchArc_2, anArcCenter, [], [])
+
+# Complete the oval hole
+SketchConstraintMirror_1_objects = [SketchLine_13.result(), SketchArc_2.results()[1], SketchLine_14.result()]
+SketchConstraintMirror_1 = Sketch_2.addMirror(SketchLine_12.result(), SketchConstraintMirror_1_objects)
+[SketchLine_15, SketchArc_3, SketchLine_16] = SketchConstraintMirror_1.mirrored()
+model.do()
+
+# =============================================================================
+# Test 7. Set arc and circle equal radii and move arc
+# =============================================================================
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchCircle_2.results()[1], SketchArc_2.results()[1])
+model.do()
+# move center of arc
+delta = [-1., -1.]
+anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+for i in range(1, 10):
+ anArcCenter = [anArcCenter[0] + delta[0], anArcCenter[1] + delta[1]]
+ Sketch_2.move(SketchArc_2.center(), anArcCenter[0], anArcCenter[1])
+ model.do()
+ model.assertArc(SketchArc_2, anArcCenter, [], [])
+ model.assertPoint(SketchCircle_2.center(), [aCircleCenter[0], anArcCenter[1]])
+ anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint())
+ assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE)
+# move arc by dragging edge
+aCircleCenter = [SketchCircle_2.center().x(), SketchCircle_2.center().y()]
+anArcCenter = [SketchArc_2.center().x(), SketchArc_2.center().y()]
+aPosition = [anArcCenter[0] + anArcRadius, anArcCenter[1]]
+delta = [1., 1.]
+for i in range(1, 10):
+ aPosition = [aPosition[0] + delta[0], aPosition[1] + delta[1]]
+ Sketch_2.move(SketchArc_2.defaultResult(), aPosition[0], aPosition[1])
+ model.do()
+ model.assertArc(SketchArc_2, anArcCenter, [], [])
+ model.assertPoint(SketchCircle_2.center(), aCircleCenter)
+ anArcRadius = model.distancePointPoint(SketchArc_2.center(), SketchArc_2.startPoint())
+ assert(math.fabs(SketchCircle_2.radius().value() - anArcRadius) < TOLERANCE)
+ if i == 5:
+ delta = [-1., -1.]
+
+# Fix all DOF in Sketch_2
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchArc_2.center(), SketchLine_9.result(), 21.5)
+SketchConstraintLength_4 = Sketch_2.setLength(SketchLine_13.result(), 3.5)
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_2.results()[1], 6.5)
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_8.result(), 30)
+model.do()
+
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchCircle_2_2r-SketchArc_2_2r-SketchLine_13r-SketchLine_14f-SketchLine_15f-SketchArc_3_2r-SketchLine_16r")], model.selection(), -165, 155)
+Boolean_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Boolean_1_1/Modified_8"))
+SketchLine_17 = Sketch_3.addLine(145, 0, 165, 0)
+SketchPoint_2 = Sketch_3.addPoint(model.selection("VERTEX", "Boolean_1_1/Modified_7&Boolean_1_1/Modified_6&Boolean_1_1/Modified_2"))
+SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchPoint_2.result())
+SketchLine_18 = Sketch_3.addLine(165, 0, 165, -20)
+SketchLine_19 = Sketch_3.addLine(165, -20, 145, -20)
+SketchLine_20 = Sketch_3.addLine(145, -20, 145, 0)
+SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_20.endPoint(), SketchLine_17.startPoint())
+SketchConstraintCoincidence_25 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint())
+SketchConstraintCoincidence_26 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchLine_19.startPoint())
+SketchConstraintCoincidence_27 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_17.result())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_18.result())
+SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_19.result())
+SketchConstraintVertical_5 = Sketch_3.setVertical(SketchLine_20.result())
+SketchArc_4 = Sketch_3.addArc(145, -20, 165, -20, 145, 0, False)
+SketchConstraintCoincidence_28 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_4.center())
+SketchConstraintCoincidence_29 = Sketch_3.setCoincident(SketchLine_18.endPoint(), SketchArc_4.startPoint())
+SketchConstraintCoincidence_30 = Sketch_3.setCoincident(SketchArc_4.endPoint(), SketchLine_20.endPoint())
+SketchConstraintRadius_3 = Sketch_3.setRadius(SketchArc_4.results()[1], 20)
+SketchArc_5 = Sketch_3.addArc(145, -20, 155, -20, 145, -10, False)
+SketchConstraintCoincidence_31 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchArc_5.center())
+SketchConstraintCoincidence_32 = Sketch_3.setCoincident(SketchLine_20.result(), SketchArc_5.endPoint())
+SketchConstraintCoincidence_33 = Sketch_3.setCoincident(SketchArc_5.startPoint(), SketchLine_19.result())
+SketchLine_21 = Sketch_3.addLine(model.selection("EDGE", "Boolean_1_1/Modified_12&Boolean_1_1/Modified_11"))
+SketchConstraintTangent_5 = Sketch_3.setTangent(SketchArc_5.results()[1], SketchLine_21.result())
+model.do()
+
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_17r-SketchLine_18r-SketchArc_4_2r")], model.selection(), model.selection("FACE", "Boolean_1_1/Modified_5"), 0, model.selection(), 0, [model.selection("SOLID", "Boolean_1_1")])
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_19r-SketchLine_20r-SketchArc_4_2f-SketchArc_5_2r")], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modfied_7"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+model.do()
+
+model.end()
+
+model.testNbResults(ExtrusionFuse_1, 1)
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [30])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [140])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [280])
+model.testResultsVolumes(ExtrusionFuse_1, [260653.824775497108930721879005432])
+
+assert(model.checkPythonDump())
aSession.startOperation()
aLineProjector = aSketchFeature.addFeature("SketchProjection")
aLineProjector.selection("ExternalFeature").selectSubShape("EDGE", "Sketch_1/Edge-SketchLine_1")
+aLineProjector.boolean("IncludeToResult").setValue(False)
aLineProjector.execute()
aCircleProjector = aSketchFeature.addFeature("SketchProjection")
aCircleProjector.selection("ExternalFeature").selectSubShape("EDGE", "Sketch_1/Edge-SketchCircle_1_2")
+aCircleProjector.boolean("IncludeToResult").setValue(False)
aCircleProjector.execute()
anArcProjector = aSketchFeature.addFeature("SketchProjection")
anArcProjector.selection("ExternalFeature").selectSubShape("EDGE", "Sketch_1/Edge-SketchArc_1_2")
+anArcProjector.boolean("IncludeToResult").setValue(False)
anArcProjector.execute()
aSession.finishOperation()
assert (model.dof(aSketchFeature) == 0)
--- /dev/null
+from salome.shaper import model
+from GeomAPI import *
+
+#==============================================================================
+# Auxiliary functions
+#==============================================================================
+
+# Project all features from 'theProjected' list.
+# Argument 'theFailed' shows indices of projections which should fail because of validator
+def testProjections(theDocument, theSketch, theProjected, theFailed):
+ # generate list of projected features
+ ind = 0
+ edgeProj = set()
+ for type, name in theProjected:
+ proj = theSketch.addProjection(model.selection(type, name), True)
+ assert(bool(proj.feature().error() != '') == bool(ind in theFailed))
+ if proj.feature().error() != '':
+ if proj.createdFeature() is not None:
+ theDocument.removeFeature(proj.createdFeature().feature())
+ theDocument.removeFeature(proj.feature())
+ model.do()
+ elif type == "EDGE":
+ edgeProj.add(proj)
+ ind += 1
+ model.do()
+ model.testNbSubShapes(theSketch, GeomAPI_Shape.EDGE, [len(edgeProj)])
+
+ # exclude some edges from result
+ NB_TO_EXCLUDE = 2
+ num = 0
+ for proj in edgeProj:
+ proj.setIncludeToResult(False)
+ num += 1
+ if num >= NB_TO_EXCLUDE:
+ break
+ model.do()
+ model.testNbSubShapes(theSketch, GeomAPI_Shape.EDGE, [len(edgeProj) - num])
+
+
+#==============================================================================
+# Initial 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(-187.9303398287678, -363.2915373234726, 182.2190183849013)
+SketchArc_1 = Sketch_1.addArc(-229.9631763073051, -65.7360230979784, -105.4201011859997, -97.06956797196608, -326.3502666769664, 19.13032715412109, False)
+SketchLine_1 = Sketch_1.addLine(-438.4308780225287, -71.00741660505224, 161.0737545348623, -582.1237015141244)
+SketchPoint_1 = Sketch_1.addPoint(-446.0706301668712, -312.4620987423343)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_2 = Sketch_2.addLine(27.19276215608871, 61.51157581079401, 72.96621462024476, 0)
+SketchLine_3 = Sketch_2.addLine(model.selection("EDGE", "PartSet/OZ"))
+SketchLine_4 = Sketch_2.addLine(model.selection("EDGE", "PartSet/OY"))
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_4.result())
+SketchLine_5 = Sketch_2.addLine(72.96621462024476, 0, 0, 0)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_2.addLine(0, 0, 0, 61.51157581079401)
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_3.startPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_3.result())
+SketchLine_7 = Sketch_2.addLine(0, 61.51157581079401, 27.19276215608871, 61.51157581079401)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchLine_7.endPoint())
+SketchConstraintHorizontal_1 = Sketch_2.setHorizontal(SketchLine_7.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_2r-SketchLine_5r-SketchLine_6r-SketchLine_7r")], model.selection(), 100, 0)
+model.do()
+
+#==============================================================================
+# Tests
+#==============================================================================
+
+aProjectedList = [("EDGE", "Sketch_1/Edge-SketchCircle_1_2"),
+ ("EDGE", "Sketch_1/Edge-SketchArc_1_2"),
+ ("EDGE", "Sketch_1/Edge-SketchLine_1"),
+ ("VERTEX", "Sketch_1/Vertex-SketchPoint_1"),
+ #
+ ("VERTEX", "Sketch_1/Vertex-SketchCircle_1"),
+ ("VERTEX", "Sketch_1/Vertex-SketchLine_1e"),
+ ("VERTEX", "Sketch_1/Vertex-SketchLine_1s"),
+ ("VERTEX", "Sketch_1/Vertex-SketchArc_1_2s"),
+ ("VERTEX", "Sketch_1/Vertex-SketchArc_1_2e"),
+ ("VERTEX", "Sketch_1/Vertex-SketchArc_1"),
+ #
+ ("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"),
+ ("VERTEX", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"),
+ #
+ ("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/From_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/From_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"),
+ #
+ ("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_3"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/Generated_Face_1"),
+ #
+ ("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_1"),
+ ("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1")
+ ]
+
+# Test projection to the same plane
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_2"))
+aFailedIDs = set([21, 29])
+testProjections(Part_1_doc, Sketch_3, aProjectedList, aFailedIDs)
+
+# Test projection to parallel plane
+Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"))
+testProjections(Part_1_doc, Sketch_4, aProjectedList, aFailedIDs)
+
+# Test projection to lower base of the prism
+Sketch_5 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/From_Face_1"))
+aFailedIDs = set([0, 1, 22, 23, 24, 25])
+testProjections(Part_1_doc, Sketch_5, aProjectedList, aFailedIDs)
+
+# Test projection to upper base of the prism
+Sketch_6 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face_1"))
+testProjections(Part_1_doc, Sketch_6, aProjectedList, aFailedIDs)
+
+# Test projection to orthogonal side face of the prism
+Sketch_7 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_1"))
+aFailedIDs = set([0, 1, 18, 20, 26, 28])
+testProjections(Part_1_doc, Sketch_7, aProjectedList, aFailedIDs)
+
+# Test projection to slope side face of the prism
+Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_3"))
+aFailedIDs = set([0, 1])
+testProjections(Part_1_doc, Sketch_8, aProjectedList, aFailedIDs)
+
+model.end()
--- /dev/null
+from salome.shaper import model
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "clearance", "210")
+model.addParameter(Part_1_doc, "wheel_R", "203")
+model.addParameter(Part_1_doc, "arc_R", "wheel_R+70")
+model.addParameter(Part_1_doc, "hood_height", "290")
+HeightParam = model.addParameter(Part_1_doc, "height", "900")
+LengthParam = model.addParameter(Part_1_doc, "length", "1460")
+PosParam = model.addParameter(Part_1_doc, "position", "71.99905090248758")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-281.378739745974, 78.99909999999998, -98.87873974597397, 78.99909999999998)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchArc_1 = Sketch_1.addArc(174.031501908677, 71.9991, -98.87873974597397, 78.99909999999998, 446.941743563328, 78.9991, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchArc_1.startPoint())
+SketchArc_2 = Sketch_1.addArc(-554.288981400625, 71.9991, -281.378739745974, 78.99909999999998, -827.1992230552759, 78.9991, False)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_1.result())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_1.result(), "clearance-wheel_R", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), "clearance-wheel_R", True)
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchArc_2.results()[1], SketchArc_1.results()[1])
+SketchCircle_1 = Sketch_1.addCircle(-554.288981400625, 71.9991, 203)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.center(), SketchCircle_1.center())
+SketchCircle_2 = Sketch_1.addCircle(174.031501908677, 71.9991, 203)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.center(), SketchCircle_2.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "wheel_R")
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+SketchLine_2 = Sketch_1.addLine(-827.1992230552759, 78.9991, -960.4001854579536, 78.9991)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-960.4001854579536, 78.9991, -960.4001854579536, 368.9991)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-891.6236641114499, 437.7756213465037, -540.5628729569305, 437.7756213465037)
+SketchLine_5 = Sketch_1.addLine(-540.5628729569305, 437.7756213465037, -349.330908394406, 768.9991)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-349.330908394406, 768.9991, 308.3678499795216, 768.9991)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(308.3678499795216, 768.9991, 499.5998145420464, 437.7756213465038)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(499.5998145420464, 437.7756213465038, 499.5998145420464, 78.9991)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(499.5998145420464, 78.9991, 446.941743563328, 78.9991)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_9.endPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_8.result())
+SketchArc_3 = Sketch_1.addArc(-891.6236641114499, 368.9991, -891.6236641114499, 437.7756213465037, -960.4001854579536, 368.9991, False)
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_3.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_3.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_4.result())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_5.result(), SketchLine_4.result(), 120.0000000000006)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.result())
+SketchConstraintAngle_2 = Sketch_1.setAngleBackward(SketchLine_7.result(), SketchLine_6.result(), 120.0000000000006)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_2.startPoint(), "arc_R", True)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchLine_5.endPoint(), "height-clearance")
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_2.endPoint(), SketchLine_9.startPoint(), "length", True)
+SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_2.result(), "hood_height", True)
+SketchLine_10 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX"))
+SketchConstraintDistance_6 = Sketch_1.setDistance(SketchCircle_2.center(), SketchLine_10.result(), "position", True)
+SketchPoint_1 = Sketch_1.addPoint(-910.4001854579535, 347.7756213465037)
+SketchPoint_2 = Sketch_1.addPoint(-910.9041532173604, 297.7781612460398)
+SketchConstraintDistance_7 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_3.result(), 50, True)
+SketchConstraintDistance_8 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_4.result(), 90, True)
+SketchConstraintDistance_9 = Sketch_1.setDistance(SketchPoint_2.coordinates(), SketchPoint_1.coordinates(), 50, True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "length/8")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchArc_1_2r-SketchArc_2_2r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchArc_3_2f")], model.selection(), 500, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 500, -400)
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 100, 0)
+model.do()
+
+# Verify point-line signed distance
+dist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1)
+dist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1)
+dist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2)
+dist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3)
+dist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4)
+
+PosParam.setValue(300)
+model.do()
+curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1)
+curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1)
+curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2)
+curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3)
+curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3)
+assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4)
+assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5)
+
+LengthParam.setValue(2000)
+model.do()
+curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1)
+curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1)
+curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2)
+curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3)
+curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3)
+assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4)
+assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5)
+
+HeightParam.setValue(1200)
+model.do()
+curDist1 = model.signedDistancePointLine(SketchArc_1.center(), SketchLine_1)
+curDist2 = model.signedDistancePointLine(SketchArc_2.center(), SketchLine_1)
+curDist3 = model.signedDistancePointLine(SketchLine_3.endPoint(), SketchLine_2)
+curDist4 = model.signedDistancePointLine(SketchPoint_1, SketchLine_3)
+curDist5 = model.signedDistancePointLine(SketchPoint_1, SketchLine_4)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+assert(math.fabs(dist3 - curDist3) < TOLERANCE), "Expected {}, actual {}".format(dist3, curDist3)
+assert(math.fabs(dist4 - curDist4) < TOLERANCE), "Expected {}, actual {}".format(dist4, curDist4)
+assert(math.fabs(dist5 - curDist5) < TOLERANCE), "Expected {}, actual {}".format(dist5, curDist5)
+
+model.end()
--- /dev/null
+from salome.shaper import model
+import math
+
+TOLERANCE = 1.e-5
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "clearance", "210")
+model.addParameter(Part_1_doc, "wheel_R", "203")
+model.addParameter(Part_1_doc, "arc_R", "wheel_R+70")
+model.addParameter(Part_1_doc, "hood_height", "290")
+HeightParam = model.addParameter(Part_1_doc, "height", "900")
+LengthParam = model.addParameter(Part_1_doc, "length", "1460")
+PosParam = model.addParameter(Part_1_doc, "position", "71.99905090248758")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-281.378739745974, 78.99909999999998, -98.87873974597397, 78.99909999999998)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchArc_1 = Sketch_1.addArc(174.031501908677, 71.9991, -98.87873974597397, 78.99909999999998, 446.941743563328, 78.9991, True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchArc_1.startPoint())
+SketchArc_2 = Sketch_1.addArc(-554.288981400625, 71.9991, -281.378739745974, 78.99909999999998, -827.1992230552759, 78.9991, False)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_1.result())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_1.result(), "clearance-wheel_R", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), "clearance-wheel_R", True)
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchArc_2.results()[1], SketchArc_1.results()[1])
+SketchCircle_1 = Sketch_1.addCircle(-554.288981400625, 71.9991, 203)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.center(), SketchCircle_1.center())
+SketchCircle_2 = Sketch_1.addCircle(174.031501908677, 71.9991, 203)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.center(), SketchCircle_2.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "wheel_R")
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+SketchLine_2 = Sketch_1.addLine(-827.1992230552759, 78.9991, -960.4001854579536, 78.9991)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-960.4001854579536, 78.9991, -960.4001854579536, 368.9991)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-891.6236641114499, 437.7756213465037, -540.5628729569305, 437.7756213465037)
+SketchLine_5 = Sketch_1.addLine(-540.5628729569305, 437.7756213465037, -349.330908394406, 768.9991)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-349.330908394406, 768.9991, 308.3678499795216, 768.9991)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(308.3678499795216, 768.9991, 499.5998145420464, 437.7756213465038)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(499.5998145420464, 437.7756213465038, 499.5998145420464, 78.9991)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(499.5998145420464, 78.9991, 446.941743563328, 78.9991)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_9.endPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_4.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintHorizontal_5 = Sketch_1.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_8.result())
+SketchArc_3 = Sketch_1.addArc(-891.6236641114499, 368.9991, -891.6236641114499, 437.7756213465037, -960.4001854579536, 368.9991, False)
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchArc_3.startPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchArc_3.endPoint(), SketchLine_3.endPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_3.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_4.result())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_5.result(), SketchLine_4.result(), 120.0000000000006)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_4.result())
+SketchConstraintAngle_2 = Sketch_1.setAngleBackward(SketchLine_7.result(), SketchLine_6.result(), 120.0000000000006)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchArc_2.center(), SketchLine_2.startPoint(), "arc_R", True)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchLine_5.endPoint(), "height-clearance")
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchLine_2.endPoint(), SketchLine_9.startPoint(), "length", True)
+SketchConstraintDistance_5 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_2.result(), "hood_height", True)
+SketchLine_10 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX"))
+SketchConstraintDistance_6 = Sketch_1.setDistance(SketchCircle_2.center(), SketchLine_10.result(), "position", True)
+SketchPoint_1 = Sketch_1.addPoint(-910.4001854579535, 347.7756213465037)
+SketchPoint_2 = Sketch_1.addPoint(-910.9041532173604, 297.7781612460398)
+SketchConstraintDistance_7 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_3.result(), 50, True)
+SketchConstraintDistance_8 = Sketch_1.setDistance(SketchPoint_1.coordinates(), SketchLine_4.result(), 90, True)
+SketchConstraintDistance_9 = Sketch_1.setDistance(SketchPoint_2.coordinates(), SketchPoint_1.coordinates(), 50, True)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), "length/8")
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchArc_1_2r-SketchArc_2_2r-SketchLine_2r-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchLine_8r-SketchLine_9r-SketchArc_3_2f")], model.selection(), 500, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 500, -400)
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f"), model.selection("FACE", "Sketch_1/Face-SketchCircle_2_2f")], model.selection(), 100, 0)
+model.do()
+
+# Verify point-point distance
+dist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint())
+dist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2)
+
+PosParam.setValue(300)
+model.do()
+curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint())
+curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+
+LengthParam.setValue(2000)
+model.do()
+curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint())
+curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+
+HeightParam.setValue(1200)
+model.do()
+curDist1 = model.distancePointPoint(SketchArc_2.center(), SketchLine_2.startPoint())
+curDist2 = model.distancePointPoint(SketchPoint_1, SketchPoint_2)
+assert(math.fabs(dist1 - curDist1) < TOLERANCE), "Expected {}, actual {}".format(dist1, curDist1)
+assert(math.fabs(dist2 - curDist2) < TOLERANCE), "Expected {}, actual {}".format(dist2, curDist2)
+
+model.end()
SketchCircle SketchMacroCircle SketchArc SketchMacroArc
SketchRectangle
SketchProjection
- SketchConstraintLength SketchConstraintRadius SketchConstraintDistance
+ SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
SketchConstraintParallel SketchConstraintPerpendicular
SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical
SketchConstraintEqual SketchConstraintTangent
</feature>
</group>
+<excluded>
+ <group id="Elliptic geometry">
+ <!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
+ <feature id="SketchEllipse"
+ title="Ellipse"
+ tooltip="Create ellipse"
+ icon="icons/Sketch/ellipse.png"
+ internal="1">
+ <sketch-2dpoint_selector id="ellipse_center"
+ title="Center"
+ tooltip="Center coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_focus"
+ title="Focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <labelvalue id="ellipse_major_radius"
+ icon="icons/Sketch/radius.png"
+ label="Major radius:"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <labelvalue id="ellipse_minor_radius"
+ icon="icons/Sketch/radius.png"
+ label="Minor radius:"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ </feature>
+ <!-- SketchMacroEllipse -->
+ <feature id="SketchMacroEllipse"
+ icon="icons/Sketch/ellipse.png"
+ title="Ellipse"
+ tooltip="Create ellipse">
+ <sketch-2dpoint_selector id="center_point"
+ reference_attribute="center_point_ref"
+ title="Center point"
+ tooltip="Center point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="major_axis_point"
+ reference_attribute="major_axis_point_ref"
+ title="Major axis point"
+ tooltip="Major axis point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="passed_point"
+ reference_attribute="passed_point_ref"
+ title="Passed point"
+ tooltip="Passed point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+<!-- <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
+ </sketch-2dpoint_selector>
+<!-- <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
+ <labelvalue id="ellipse_major_radius"
+ icon="icons/Sketch/radius.png"
+ label="Major radius:"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ <validator id="GeomValidators_Positive"/>
+ </labelvalue>
+ <labelvalue id="ellipse_minor_radius"
+ icon="icons/Sketch/radius.png"
+ label="Minor radius:"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ <validator id="GeomValidators_Positive"/>
+ </labelvalue>
+ <boolvalue id="Auxiliary"
+ tooltip="Construction element"
+ label="Auxiliary"
+ default="false"
+ obligatory="0"/>
+ </feature>
+ </group>
+</excluded>
+
<group id="Projection">
<!-- Intersection Point -->
<!-- feature
id="ExternalFeature"
label="Edge"
tooltip="Select external edge."
- shape_types="edge"
+ shape_types="edge vertex"
use_external="true"
can_create_external="false"
use_sketch_plane="false">
<validator id="SketchPlugin_ProjectionValidator"/>
</sketch_shape_selector>
+ <boolvalue id="IncludeToResult" label="Include into the sketch result" default="true" tooltip="Include projected feature into the sketch result"/>
<validator id="PartSet_ProjectionSelection"/>
</feature>
</group>
<validator id="GeomValidators_Positive"/>
</doublevalue_editor>
+ <boolvalue id="SignedDistance" label="Keep orientation" default="true" tooltip="Keep distance orientation" obligatory="0"/>
+ <validator id="PartSet_DistanceSelection"/>
+ </feature>
+
+ <!-- SketchConstraintDistanceHorizontal -->
+ <feature
+ id="SketchConstraintDistanceHorizontal"
+ title="Horizontal Distance"
+ tooltip="Set horizontal distance between two points"
+ icon="icons/Sketch/distance_h.png">
+ <label title="Select points for distance definition."/>
+ <sketch_shape_selector
+ id="ConstraintEntityA"
+ label="First point"
+ tooltip="Select point."
+ shape_types="vertex">
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+ </sketch_shape_selector>
+ <sketch_shape_selector
+ id="ConstraintEntityB"
+ label="Second point"
+ tooltip="Select point."
+ shape_types="vertex">
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+ </sketch_shape_selector>
+ <sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
+
+ <doublevalue_editor label="Value" tooltip="Distance" id="ConstraintValue" default="computed"/>
+
+ <validator id="PartSet_DistanceSelection"/>
+ </feature>
+
+ <!-- SketchConstraintDistanceVertical -->
+ <feature
+ id="SketchConstraintDistanceVertical"
+ title="Vertical Distance"
+ tooltip="Set vertical distance between two points"
+ icon="icons/Sketch/distance_v.png">
+ <label title="Select points for distance definition."/>
+ <sketch_shape_selector
+ id="ConstraintEntityA"
+ label="First point"
+ tooltip="Select point."
+ shape_types="vertex">
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+ </sketch_shape_selector>
+ <sketch_shape_selector
+ id="ConstraintEntityB"
+ label="Second point"
+ tooltip="Select point."
+ shape_types="vertex">
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex"/>
+ </sketch_shape_selector>
+ <sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
+
+ <doublevalue_editor label="Value" tooltip="Distance" id="ConstraintValue" default="computed"/>
+
<validator id="PartSet_DistanceSelection"/>
</feature>
- <!-- SketchConstraintLength -->
+ <!-- SketchConstraintLength -->
<feature id="SketchConstraintLength" title="Length" tooltip="Set fixed length of a line segment" icon="icons/Sketch/length.png">
<label title="Select a line on which to calculate length" tooltip="Select a line on which to calculate length"/>
<shape_selector id="ConstraintEntityA" label="Line" tooltip="Select a line" shape_types="edge" >
<sketch_shape_selector id="ConstraintEntityA"
label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
<validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_HasNoConstraint" parameters="SketchConstraintHorizontal, SketchConstraintVertical"/>
</sketch_shape_selector>
<validator id="PartSet_HVDirSelection"/>
</feature>
<sketch_shape_selector id="ConstraintEntityA"
label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
<validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_HasNoConstraint" parameters="SketchConstraintHorizontal, SketchConstraintVertical"/>
</sketch_shape_selector>
<validator id="PartSet_HVDirSelection"/>
</feature>
SketchSolver_ConstraintMulti.h
SketchSolver_ConstraintMultiRotation.h
SketchSolver_ConstraintMultiTranslation.h
+ SketchSolver_ConstraintMovement.h
)
SET(SKETCHSOLVER_SOURCES
SketchSolver_ConstraintMulti.cpp
SketchSolver_ConstraintMultiRotation.cpp
SketchSolver_ConstraintMultiTranslation.cpp
+ SketchSolver_ConstraintMovement.cpp
)
SET(SKETCHSOLVER_LIBRARIES
${SKETCHSOLVER_CONSTRAINT_SOURCES}
)
+if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE})
+ ADD_DEFINITIONS(-DCHANGE_RADIUS_WHILE_MOVE)
+endif()
+
ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES})
TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES} ${SKETCHSOLVER_LIBRARIES})
INSTALL(TARGETS PlaneGCSSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
// Predefined values for identifiers
const ConstraintID CID_UNKNOWN = 0;
const ConstraintID CID_MOVEMENT = -1;
+const ConstraintID CID_FICTIVE = 1024;
/// Types of entities
enum SketchSolver_EntityType {
CONSTRAINT_DISTANCE, // base distance if we don't know the measured objects yet
CONSTRAINT_PT_PT_DISTANCE,
CONSTRAINT_PT_LINE_DISTANCE,
+ CONSTRAINT_HORIZONTAL_DISTANCE,
+ CONSTRAINT_VERTICAL_DISTANCE,
CONSTRAINT_RADIUS,
CONSTRAINT_ANGLE,
CONSTRAINT_FIXED,
myDiagnoseBeforeSolve(false),
myInitilized(false),
myConfCollected(false),
- myDOF(0)
+ myDOF(0),
+ myFictiveConstraint(0)
{
}
myConstraints.clear();
myConflictingIDs.clear();
myDOF = 0;
+
+ removeFictiveConstraint();
}
void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
void PlaneGCSSolver_Solver::initialize()
{
Events_LongOp::start(this);
+ addFictiveConstraintIfNecessary();
if (myDiagnoseBeforeSolve)
diagnose();
myEquationSystem->declareUnknowns(myParameters);
if (myInitilized) {
aResult = (GCS::SolveStatus)myEquationSystem->solve();
} else {
+ addFictiveConstraintIfNecessary();
+
if (myDiagnoseBeforeSolve)
diagnose();
aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
collectConflicting();
if (!myConflictingIDs.empty())
aResult = GCS::Failed;
+ else if (aResult == GCS::Failed) {
+ // DogLeg solver failed without conflicting constraints, try to use Levenberg-Marquardt solver
+ // if there are point-line distance constraints
+ ConstraintMap::iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end(); ++aCIt) {
+ if (aCIt->second.size() <= 1)
+ continue;
+ std::set<GCSConstraintPtr>::const_iterator anIt = aCIt->second.begin();
+ for (; anIt != aCIt->second.end(); ++anIt)
+ if ((*anIt)->getTypeId() == GCS::P2LDistance)
+ break;
+ if (anIt != aCIt->second.end())
+ break;
+ }
+
+ if (aCIt != myConstraints.end()) {
+ aResult = (GCS::SolveStatus)myEquationSystem->solve(
+ myParameters, true, GCS::LevenbergMarquardt);
+ myConfCollected = false;
+ collectConflicting();
+ if (!myConflictingIDs.empty())
+ aResult = GCS::Failed;
+ }
+ }
SolveStatus aStatus;
if (aResult == GCS::Failed)
aStatus = STATUS_OK;
}
+ removeFictiveConstraint();
myInitilized = false;
return aStatus;
}
myDOF = myEquationSystem->diagnose();
myDiagnoseBeforeSolve = false;
}
+
+void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary()
+{
+ if (!myConstraints.empty() &&
+ myConstraints.find(CID_MOVEMENT) == myConstraints.end())
+ return;
+
+ if (myFictiveConstraint)
+ return; // no need several fictive constraints
+
+ double* aParam = createParameter();
+ double* aFictiveParameter = new double(0.0);
+
+ myFictiveConstraint = new GCS::ConstraintEqual(aFictiveParameter, aParam);
+ myFictiveConstraint->setTag(CID_FICTIVE);
+ myEquationSystem->addConstraint(myFictiveConstraint);
+}
+
+void PlaneGCSSolver_Solver::removeFictiveConstraint()
+{
+ if (myFictiveConstraint) {
+ myEquationSystem->removeConstraint(myFictiveConstraint);
+ myParameters.pop_back();
+
+ GCS::VEC_pD aParams = myFictiveConstraint->params();
+ for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++ anIt)
+ delete *anIt;
+ delete myFictiveConstraint;
+ myFictiveConstraint = 0;
+ }
+}
private:
void collectConflicting();
+ /// \brief Add fictive constraint if the sketch contains temporary constraints only
+ void addFictiveConstraintIfNecessary();
+ /// \brief Remove previously added fictive constraint
+ void removeFictiveConstraint();
+
private:
typedef std::map<ConstraintID, std::set<GCSConstraintPtr> > ConstraintMap;
bool myConfCollected;
int myDOF; ///< degrees of freedom
+
+ GCS::Constraint* myFictiveConstraint;
};
typedef std::shared_ptr<PlaneGCSSolver_Solver> SolverPtr;
constraintsToSolver(theSolverConstraint, mySketchSolver);
}
-void PlaneGCSSolver_Storage::addTemporaryConstraint(
+void PlaneGCSSolver_Storage::addMovementConstraint(
const ConstraintWrapperPtr& theSolverConstraint)
{
- if (myConstraintMap.empty())
- return; // no need to process temporary constraints if there is no active constraint
-
// before adding movement constraint to solver, re-check its DOF
if (mySketchSolver->dof() == 0)
mySketchSolver->diagnose();
virtual void addConstraint(ConstraintPtr theConstraint,
ConstraintWrapperPtr theSolverConstraint);
- /// \brief Add list of temporary constraints which will be destroyed
+ /// \brief Add a movement constraint which will be destroyed
/// after the next solving of the set of constraints.
/// \param theSolverConstraint [in] solver's constraint
- virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint);
+ virtual void addMovementConstraint(const ConstraintWrapperPtr& theSolverConstraint);
/// \brief Convert feature to the form applicable for specific solver and map it
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMiddle.h>
createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintHVDistance(const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
static ConstraintWrapperPtr
createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
- } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID()) {
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint));
return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
}
-std::shared_ptr<SketchSolver_ConstraintFixed> PlaneGCSSolver_Tools::createMovementConstraint(
+std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
FeaturePtr theMovedFeature)
{
- return std::shared_ptr<SketchSolver_ConstraintFixed>(
- new SketchSolver_ConstraintFixed(theMovedFeature));
+ return std::shared_ptr<SketchSolver_ConstraintMovement>(
+ new SketchSolver_ConstraintMovement(theMovedFeature));
+}
+
+std::shared_ptr<SketchSolver_ConstraintMovement> PlaneGCSSolver_Tools::createMovementConstraint(
+ AttributePtr theMovedAttribute)
+{
+ return std::shared_ptr<SketchSolver_ConstraintMovement>(
+ new SketchSolver_ConstraintMovement(theMovedAttribute));
}
aPoint1,
GCS_EDGE_WRAPPER(theEntity1));
break;
+ case CONSTRAINT_HORIZONTAL_DISTANCE:
+ case CONSTRAINT_VERTICAL_DISTANCE:
+ aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
+ break;
case CONSTRAINT_RADIUS:
aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
GCS_EDGE_WRAPPER(theEntity1));
return aResult;
}
+ConstraintWrapperPtr createConstraintHVDistance(
+ const SketchSolver_ConstraintType& theType,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
+{
+ GCSPointPtr aPoint1 = thePoint1->point();
+ GCSPointPtr aPoint2 = thePoint2->point();
+
+ double *aParam1, *aParam2;
+ if (theType == CONSTRAINT_HORIZONTAL_DISTANCE) {
+ aParam1 = aPoint1->x;
+ aParam2 = aPoint2->x;
+ } else if (theType == CONSTRAINT_VERTICAL_DISTANCE) {
+ aParam1 = aPoint1->y;
+ aParam2 = aPoint2->y;
+ }
+
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintDifference(aParam1, aParam2, theValue->scalar()));
+
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
+ aResult->setValueParameter(theValue);
+ return aResult;
+}
+
ConstraintWrapperPtr createConstraintRadius(
std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
#define PlaneGCSSolver_Tools_H_
#include <SketchSolver_Constraint.h>
-#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintMovement.h>
#include <SketchPlugin_Constraint.h>
#include <GeomAPI_Lin2d.h>
SolverConstraintPtr createConstraint(ConstraintPtr theConstraint);
/// \brief Creates temporary constraint to fix the feature after movement
- std::shared_ptr<SketchSolver_ConstraintFixed>
+ std::shared_ptr<SketchSolver_ConstraintMovement>
createMovementConstraint(FeaturePtr theMovedFeature);
+ /// \brief Creates temporary constraint to fix the attribute after movement
+ std::shared_ptr<SketchSolver_ConstraintMovement>
+ createMovementConstraint(AttributePtr theMovedAttribute);
/// \brief Creates new constraint using given parameters
/// \param theConstraint [in] original constraint
ConstraintWrapperPtr aNewConstraint = PlaneGCSSolver_Tools::createConstraint(
myBaseConstraint, aConstrType,
aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+ if (!aNewConstraint) {
+ myErrorMsg = SketchSolver_Error::WRONG_CONSTRAINT_TYPE();
+ return;
+ }
myStorage->addConstraint(myBaseConstraint, aNewConstraint);
adjustConstraint();
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_Storage.h>
+#include <PlaneGCSSolver_Tools.h>
+
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
+
#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Lin2d.h>
#include <GeomAPI_Pnt2d.h>
return;
}
- if (theAttributes[1])
- myType = CONSTRAINT_PT_PT_DISTANCE;
- else if (theAttributes[2] && theAttributes[2]->type() == ENTITY_LINE)
+ if (theAttributes[1]) {
+ if (myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
+ myType = CONSTRAINT_HORIZONTAL_DISTANCE;
+ else if (myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
+ myType = CONSTRAINT_VERTICAL_DISTANCE;
+ else
+ myType = CONSTRAINT_PT_PT_DISTANCE;
+ } else if (theAttributes[2] && theAttributes[2]->type() == ENTITY_LINE)
myType = CONSTRAINT_PT_LINE_DISTANCE;
else
theAttributes.clear();
void SketchSolver_ConstraintDistance::adjustConstraint()
{
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
+ if (getType() == CONSTRAINT_PT_LINE_DISTANCE) {
+ bool isSigned = myBaseConstraint->boolean(SketchPlugin_ConstraintDistance::SIGNED())->value();
+ if (myIsSigned == isSigned)
+ return; // distance type is not changed => nothing to adjust
- // Adjust point-point distance if the points are equal
- if (getType() == CONSTRAINT_PT_PT_DISTANCE) {
-//// AttributePtr aPt1 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
-//// AttributePtr aPt2 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B());
-////
-//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-//// std::shared_ptr<GeomAPI_Pnt2d> aPoint1 = aBuilder->point(myStorage->entity(aPt1));
-//// EntityWrapperPtr anEntity2 = myStorage->entity(aPt2);
-//// std::shared_ptr<GeomAPI_Pnt2d> aPoint2 = aBuilder->point(anEntity2);
-////
-//////// if (aPoint1->distance(aPoint2) < tolerance) {
-//////// // Change X coordinate of second point to eliminate coincidence
-//////// ParameterWrapperPtr aX = aSubs.back()->parameters().front();
-//////// aX->setValue(aX->value() + 1.0);
-//////// myStorage->update(aX);
-//////// }
- return;
- }
-
- // Adjust point-line distance
- if (fabs(myPrevValue) == fabs(aConstraint->value())) {
- // sign of distance is not changed
-//// aConstraint->setValue(myPrevValue);
-//// myStorage->addConstraint(myBaseConstraint, aConstraint);
- return;
+ // Adjust point-line distance by setting/removing additional constraints
+ if (isSigned)
+ addConstraintsToKeepSign();
+ else
+ removeConstraintsKeepingSign();
+ myIsSigned = isSigned;
}
-
-//// // Adjust the sign of constraint value
-//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-////
-//// std::shared_ptr<GeomAPI_Lin2d> aLine;
-//// std::shared_ptr<GeomAPI_Pnt2d> aPoint;
-//// for (int i = 0; i < 2; ++i) {
-//// AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
-//// EntityWrapperPtr anEntity = myStorage->entity(anAttr);
-//// if (anEntity->type() == ENTITY_POINT)
-//// aPoint = aBuilder->point(anEntity);
-//// else if (anEntity->type() == ENTITY_LINE)
-//// aLine = aBuilder->line(anEntity);
-//// }
-////
-//// std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
-//// std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
-//// if (aLineVec->cross(aPtLineVec) * aConstraint->value() < 0.0)
-//// aConstraint->setValue(aConstraint->value() * (-1.0));
}
void SketchSolver_ConstraintDistance::update()
SketchSolver_Constraint::update();
}
+
+void SketchSolver_ConstraintDistance::addConstraintsToKeepSign()
+{
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
+ ConstraintWrapperPtr aConstraint = aStorage->constraint(myBaseConstraint);
+ std::list<GCSConstraintPtr> aGCSConstraints = aConstraint->constraints();
+
+ // calculate projection of the point on the line and find a sign of a distance
+ EntityWrapperPtr aDistPoint, aDistLine;
+ for (int i = 0; i < 2; ++i) {
+ AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
+ EntityWrapperPtr anEntity = myStorage->entity(anAttr);
+ if (anEntity->type() == ENTITY_POINT)
+ aDistPoint = anEntity;
+ else if (anEntity->type() == ENTITY_LINE)
+ aDistLine = anEntity;
+ }
+ std::shared_ptr<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(aDistLine);
+ std::shared_ptr<GeomAPI_Pnt2d> aPoint = PlaneGCSSolver_Tools::point(aDistPoint);
+
+ std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+ std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+ if (aLineVec->cross(aPtLineVec) >= 0.)
+ mySignValue = PI/2.0;
+ else
+ mySignValue = - PI/2.0;
+ double aDot = aPtLineVec->dot(aLineVec);
+ std::shared_ptr<GeomAPI_XY> aProjectedPnt =
+ aLine->location()->xy()->added(aLineVec->multiplied(aDot));
+
+ // create auxiliary point on the line and set auxiliary constraints
+ myOddPoint = GCSPointPtr(new GCS::Point);
+ myOddPoint->x = aStorage->createParameter();
+ myOddPoint->y = aStorage->createParameter();
+ *(myOddPoint->x) = aProjectedPnt->x();
+ *(myOddPoint->y) = aProjectedPnt->y();
+
+ PointWrapperPtr aPointWr = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aDistPoint);
+ EdgeWrapperPtr anEdgeWr = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aDistLine);
+ std::shared_ptr<GCS::Line> aGCSLine = std::dynamic_pointer_cast<GCS::Line>(anEdgeWr->entity());
+ // point-on-line
+ GCSConstraintPtr aNewConstraint(new GCS::ConstraintPointOnLine(*myOddPoint, *aGCSLine));
+ aGCSConstraints.push_back(aNewConstraint);
+ // angle which keep orientation
+ aNewConstraint = GCSConstraintPtr(new GCS::ConstraintL2LAngle(
+ aGCSLine->p1, aGCSLine->p2, *myOddPoint, *(aPointWr->point()), &mySignValue));
+ aGCSConstraints.push_back(aNewConstraint);
+
+ aConstraint->setConstraints(aGCSConstraints);
+
+ aStorage->removeConstraint(myBaseConstraint);
+ aStorage->addConstraint(myBaseConstraint, aConstraint);
+}
+
+void SketchSolver_ConstraintDistance::removeConstraintsKeepingSign()
+{
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
+ ConstraintWrapperPtr aConstraint = aStorage->constraint(myBaseConstraint);
+ std::list<GCSConstraintPtr> aGCSConstraints = aConstraint->constraints();
+
+ aStorage->removeConstraint(myBaseConstraint);
+
+ // remove parameters related to auxiliary point
+ GCS::SET_pD aParams;
+ aParams.insert(myOddPoint->x);
+ aParams.insert(myOddPoint->y);
+ aStorage->removeParameters(aParams);
+
+ aGCSConstraints.pop_back();
+ aGCSConstraints.pop_back();
+ aConstraint->setConstraints(aGCSConstraints);
+ aStorage->addConstraint(myBaseConstraint, aConstraint);
+}
/// Constructor based on SketchPlugin constraint
SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
SketchSolver_Constraint(theConstraint),
- myIsNegative(false)
+ myIsSigned(false),
+ mySignValue(0.0)
{}
/// \brief Update constraint
virtual void adjustConstraint();
private:
- double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
+ void addConstraintsToKeepSign();
+ void removeConstraintsKeepingSign();
- /// \c true, if the point if placed rightside of line direction (SLVS_C_PT_LINE_DISTANCE only)
- bool myIsNegative;
+private:
+ double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
+ bool myIsSigned; ///< true if the sign of point-line distance should be kept everytime
+ GCSPointPtr myOddPoint; ///< auxiliary point to keep sign of distance
+ double mySignValue;
};
#endif
--- /dev/null
+// Copyright (C) 2017 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 <SketchSolver_ConstraintMovement.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Manager.h>
+
+#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomAPI_Pnt2d.h>
+
+
+SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
+ : SketchSolver_ConstraintFixed(ConstraintPtr()),
+ myMovedFeature(theFeature),
+ mySimpleMove(true)
+{
+}
+
+SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(AttributePtr thePoint)
+ : SketchSolver_ConstraintFixed(ConstraintPtr()),
+ myDraggedPoint(thePoint),
+ mySimpleMove(true)
+{
+ myMovedFeature = ModelAPI_Feature::feature(thePoint->owner());
+}
+
+void SketchSolver_ConstraintMovement::blockEvents(bool isBlocked)
+{
+ if (myMovedFeature)
+ myMovedFeature->data()->blockSendAttributeUpdated(isBlocked);
+}
+
+void SketchSolver_ConstraintMovement::process()
+{
+ cleanErrorMsg();
+ if (!myMovedFeature || !myStorage) {
+ // Not enough parameters are initialized
+ return;
+ }
+
+ mySolverConstraint = initMovement();
+ if (!myErrorMsg.empty() || !mySolverConstraint) {
+ // Nothing to move, clear the feature to avoid changing its group
+ // after removing the Movement constraint.
+ myMovedFeature = FeaturePtr();
+ return;
+ }
+ myStorage->addMovementConstraint(mySolverConstraint);
+}
+
+
+static bool isSimpleMove(FeaturePtr theMovedFeature, AttributePtr theDraggedPoint)
+{
+ bool isSimple = true;
+#ifdef CHANGE_RADIUS_WHILE_MOVE
+ if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
+ isSimple = (theDraggedPoint.get() != 0);
+ else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
+ isSimple = (theDraggedPoint.get() != 0 &&
+ theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID());
+ }
+#endif
+ return isSimple;
+}
+
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::initMovement()
+{
+ ConstraintWrapperPtr aConstraint;
+
+ // if the feature is copy, do not move it
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(myMovedFeature);
+ if (!aSketchFeature || aSketchFeature->isCopy()) {
+ myStorage->setNeedToResolve(true);
+ return aConstraint;
+ }
+
+ EntityWrapperPtr anEntity =
+ myDraggedPoint ? myStorage->entity(myDraggedPoint) : myStorage->entity(myMovedFeature);
+ if (!anEntity) {
+ myStorage->update(myMovedFeature, true);
+ anEntity =
+ myDraggedPoint ? myStorage->entity(myDraggedPoint) : myStorage->entity(myMovedFeature);
+ if (!anEntity)
+ return aConstraint;
+ }
+
+ mySimpleMove = isSimpleMove(myMovedFeature, myDraggedPoint);
+
+ if (mySimpleMove)
+ aConstraint = fixFeature(anEntity);
+ else {
+ if (myDraggedPoint) // start or end point of arc has been moved
+ aConstraint = fixArcExtremity(anEntity);
+ else // arc or circle has been moved
+ aConstraint = fixPointOnCircle(anEntity);
+ }
+
+ return aConstraint;
+}
+
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixArcExtremity(
+ const EntityWrapperPtr& theArcExtremity)
+{
+ static const int nbParams = 4;
+ myFixedValues.reserve(nbParams); // moved point and center of arc
+
+ EdgeWrapperPtr aCircularEntity = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(
+ myStorage->entity(myMovedFeature));
+ std::shared_ptr<GCS::Arc> anArc =
+ std::dynamic_pointer_cast<GCS::Arc>(aCircularEntity->entity());
+
+ PointWrapperPtr aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theArcExtremity);
+
+ double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y,
+ anArc->center.x, anArc->center.y };
+
+ std::list<GCSConstraintPtr> aConstraints;
+ for (int i = 0; i < nbParams; ++i) {
+ myFixedValues.push_back(*aParams[i]);
+ GCSConstraintPtr aNewConstraint(new GCS::ConstraintEqual(&myFixedValues[i], aParams[i]));
+ aNewConstraint->rescale(0.01);
+ aConstraints.push_back(aNewConstraint);
+ }
+
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+}
+
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnCircle(
+ const EntityWrapperPtr& theCircular)
+{
+ static const double scale = 0.01;
+ static const int nbParams = 4;
+ myFixedValues.reserve(nbParams); // moved point and center of arc/circle
+
+ EdgeWrapperPtr aCircularEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theCircular);
+ std::shared_ptr<GCS::Circle> aCircular =
+ std::dynamic_pointer_cast<GCS::Circle>(aCircularEntity->entity());
+
+ // initialize fixed values
+ myFixedValues.push_back(*aCircular->center.x + *aCircular->rad);
+ myFixedValues.push_back(*aCircular->center.y);
+ myFixedValues.push_back(*aCircular->center.x);
+ myFixedValues.push_back(*aCircular->center.y);
+
+ // create a moved point
+ GCS::Point aPointOnCircle;
+ aPointOnCircle.x = &myFixedValues[0];
+ aPointOnCircle.y = &myFixedValues[1];
+
+ std::list<GCSConstraintPtr> aConstraints;
+ // point-on-circle
+ GCSConstraintPtr aNewConstraint(
+ new GCS::ConstraintP2PDistance(aPointOnCircle, aCircular->center, aCircular->rad));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (x)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[2], aCircular->center.x));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (y)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[3], aCircular->center.y));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+}
+
+
+void SketchSolver_ConstraintMovement::startPoint(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint)
+{
+ myStartPoint = theStartPoint;
+ if (!mySimpleMove) {
+ myFixedValues[0] = myStartPoint->x();
+ myFixedValues[1] = myStartPoint->y();
+ }
+}
+
+void SketchSolver_ConstraintMovement::moveTo(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theDestinationPoint)
+{
+ double aDelta[2] = { theDestinationPoint->x() - myStartPoint->x(),
+ theDestinationPoint->y() - myStartPoint->y() };
+
+#ifdef CHANGE_RADIUS_WHILE_MOVE
+ int aMaxSize = mySimpleMove ? (int)myFixedValues.size() : 2;
+#else
+ int aMaxSize = myMovedFeature->getKind() == SketchPlugin_Line::ID() && !myDraggedPoint ? 4 : 2;
+#endif
+ for (int i = 0; i < aMaxSize; ++i)
+ myFixedValues[i] += aDelta[i % 2];
+}
--- /dev/null
+// Copyright (C) 2017 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>
+//
+
+// File: SketchSolver_ConstraintMovement.h
+// Created: 15 Jun 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMovement_H_
+#define SketchSolver_ConstraintMovement_H_
+
+#include <SketchSolver_ConstraintFixed.h>
+
+class GeomAPI_Pnt2d;
+
+/** \class SketchSolver_ConstraintMovement
+ * \ingroup Plugins
+ * \brief Stores data to the Fixed constraint for the moved feature only
+ */
+class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
+{
+public:
+ /// Creates movement constraint based on feature
+ SketchSolver_ConstraintMovement(FeaturePtr theFeature);
+
+ /// Creates movement constraint based on point
+ SketchSolver_ConstraintMovement(AttributePtr thePoint);
+
+ /// \brief Set coordinates of the start point of the movement
+ void startPoint(const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint);
+
+ /// \brief Set coordinates of fixed feature to the values where it has been dragged.
+ /// Useful when the feature is being moved.
+ void moveTo(const std::shared_ptr<GeomAPI_Pnt2d>& theDestinationPoint);
+
+ /// \brief Block or unblock events from this constraint
+ virtual void blockEvents(bool isBlocked);
+
+ /// \brief Returns moved feature
+ FeaturePtr movedFeature() const
+ { return myMovedFeature; }
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Create Fixed constraint for the feature basing on its type and moved point
+ /// \return Fixed constraint
+ ConstraintWrapperPtr initMovement();
+
+ /// \brief Create constraint to fix moved arc extremity
+ ConstraintWrapperPtr fixArcExtremity(const EntityWrapperPtr& theArcExtremity);
+
+ /// \brief Creat constraint to fix moved point on circle/arc
+ ConstraintWrapperPtr fixPointOnCircle(const EntityWrapperPtr& theCircular);
+
+private:
+ FeaturePtr myMovedFeature; ///< fixed feature (if set, myBaseConstraint should be NULL)
+ AttributePtr myDraggedPoint; ///< one of the feature points which has been moved
+ std::shared_ptr<GeomAPI_Pnt2d> myStartPoint; ///< start point of the movement
+
+ bool mySimpleMove; ///< simple move, thus all parameters should be increased by movement delta
+};
+
+#endif
static const std::string MY_ERROR_VALUE("Caution: SolveSpace crash! Constraints are wrong");
return MY_ERROR_VALUE;
}
+ /// Constraint has wrong type
+ inline static const std::string& WRONG_CONSTRAINT_TYPE()
+ {
+ static const std::string MY_ERROR_VALUE("Unsupported type of constraint");
+ return MY_ERROR_VALUE;
+ }
};
#endif
// ========================================================
-// ========= SketchSolver_Group ===============
+// ========= SketchSolver_Group ===============
// ========================================================
SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
return myStorage->update(theFeature);
}
-bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
+template <class Type>
+static SolverConstraintPtr move(StoragePtr theStorage,
+ SolverPtr theSketchSolver,
+ int theSketchDOF,
+ bool theEventsBlocked,
+ Type theFeatureOrPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo)
{
- bool isFeatureExists = (myStorage->entity(theFeature).get() != 0);
- if (myDOF == 0 && isFeatureExists) {
+ bool isEntityExists = (theStorage->entity(theFeatureOrPoint).get() != 0);
+ if (theSketchDOF == 0 && isEntityExists) {
// avoid moving elements of fully constrained sketch
- myStorage->refresh();
- return true;
+ theStorage->refresh();
+ return SolverConstraintPtr();
}
// Create temporary Fixed constraint
- std::shared_ptr<SketchSolver_ConstraintFixed> aConstraint =
- PlaneGCSSolver_Tools::createMovementConstraint(theFeature);
- if (!aConstraint)
- return false;
- SolverConstraintPtr(aConstraint)->process(myStorage, myIsEventsBlocked);
- if (aConstraint->error().empty()) {
- setTemporary(aConstraint);
- if (!myStorage->isEmpty())
- myStorage->setNeedToResolve(true);
-
- mySketchSolver->initialize();
- aConstraint->moveFeature();
+ std::shared_ptr<SketchSolver_ConstraintMovement> aConstraint =
+ PlaneGCSSolver_Tools::createMovementConstraint(theFeatureOrPoint);
+ if (aConstraint) {
+ SolverConstraintPtr(aConstraint)->process(theStorage, theEventsBlocked);
+ if (aConstraint->error().empty()) {
+ aConstraint->startPoint(theFrom);
+ theSketchSolver->initialize();
+ aConstraint->moveTo(theTo);
+ theStorage->setNeedToResolve(true);
+ } else
+ theStorage->notify(aConstraint->movedFeature());
}
- // notify all observers that theFeature has been changed
- myStorage->notify(theFeature);
+ return aConstraint;
+}
+
+bool SketchSolver_Group::moveFeature(FeaturePtr theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo)
+{
+ SolverConstraintPtr aConstraint =
+ move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, theFeature, theFrom, theTo);
+ setTemporary(aConstraint);
+ return true;
+}
+
+bool SketchSolver_Group::movePoint(AttributePtr theAttribute,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo)
+{
+ SolverConstraintPtr aConstraint =
+ move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, theAttribute, theFrom, theTo);
+ setTemporary(aConstraint);
return true;
}
// ============================================================================
void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint)
{
- myTempConstraints.insert(theConstraint);
+ if (theConstraint)
+ myTempConstraints.insert(theConstraint);
}
// ============================================================================
#include <memory>
#include <map>
+class GeomAPI_Pnt2d;
+
typedef std::map<ConstraintPtr, SolverConstraintPtr> ConstraintConstraintMap;
/** \class SketchSolver_Group
bool updateFeature(FeaturePtr theFeature);
/** \brief Updates the data corresponding the specified feature moved in GUI.
- * Additional Fixed constraints are created.
+ * Special kind of Fixed constraints is created.
* \param[in] theFeature the feature to be updated
- * \return \c true, if the feature is moved
+ * \param[in] theFrom start point of the movement
+ * \param[in] theTo final point of the movement
+ * \return \c true, if the feature is really moved
+ */
+ bool moveFeature(FeaturePtr theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo);
+ /** \brief Updates the data corresponding the specified point moved in GUI.
+ * Special kind of Fixed constraints is created.
+ * \param[in] thePoint the attribute to be updated
+ * \param[in] theFrom start point of the movement
+ * \param[in] theTo final point of the movement
+ * \return \c true, if the attribute is really moved
*/
- bool moveFeature(FeaturePtr theFeature);
+ bool movePoint(AttributePtr thePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo);
/// Returns the current workplane
inline const CompositeFeaturePtr& getWorkplane() const
}
// ============================================================================
-// Function: changeConstraintOrEntity
+// Function: updateFeature
// Purpose: create/update the constraint or the feature and place it into appropriate group
// ============================================================================
bool SketchSolver_Manager::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature,
return isOk;
}
+// ============================================================================
+// Function: moveFeature
+// Purpose: move given feature in appropriate group
+// ============================================================================
+bool SketchSolver_Manager::moveFeature(
+ const std::shared_ptr<SketchPlugin_Feature>& theMovedFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo)
+{
+ SketchGroupPtr aGroup = findGroup(theMovedFeature);
+ if (!aGroup)
+ return false;
+
+ std::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ std::dynamic_pointer_cast<SketchPlugin_Constraint>(theMovedFeature);
+ if (aConstraint)
+ {
+ std::shared_ptr<GeomDataAPI_Point2D> aPntAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ aPntAttr->setValue(theTo);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ return true;
+ }
+
+ aGroup->blockEvents(true);
+ return aGroup->moveFeature(theMovedFeature, theFrom, theTo);
+}
+
+// ============================================================================
+// Function: moveAttribute
+// Purpose: move given attribute in appropriate group
+// ============================================================================
+bool SketchSolver_Manager::moveAttribute(
+ const std::shared_ptr<GeomDataAPI_Point2D>& theMovedAttribute,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFrom,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theTo)
+{
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theMovedAttribute->owner());
+ std::shared_ptr<SketchPlugin_Constraint> aConstraint =
+ std::dynamic_pointer_cast<SketchPlugin_Constraint>(anOwner);
+ if (aConstraint)
+ {
+ theMovedAttribute->setValue(theTo);
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ return true;
+ }
+
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anOwner);
+ SketchGroupPtr aGroup;
+ if (aSketchFeature)
+ aGroup = findGroup(aSketchFeature);
+ if (!aGroup) {
+ theMovedAttribute->setValue(theTo);
+ return false;
+ }
+
+ aGroup->blockEvents(true);
+ return aGroup->movePoint(theMovedAttribute, theFrom, theTo);
+}
+
// ============================================================================
// Function: findGroup
// Purpose: search groups of entities interacting with given feature
#include <SketchSolver_Group.h>
#include <Events_Listener.h>
-#include <SketchPlugin_Constraint.h>
#include <list>
#include <set>
+class GeomAPI_Pnt2d;
+class GeomDataAPI_Point2D;
+class SketchPlugin_Constraint;
+
/** \class SketchSolver_Manager
* \ingroup Plugins
* \brief Listens the changes of SketchPlugin features and transforms the Constraint
*/
bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature, bool theMoved = false);
+ /** \brief Move feature
+ * \param[in] theMovedFeature dragged sketch feature
+ * \param[in] theFromPoint original position of the feature
+ * \param[in] theToPoint prefereble position of the feature (current position of the mouse)
+ * \return \c true if the feature has been changed successfully
+ */
+ bool moveFeature(const std::shared_ptr<SketchPlugin_Feature>& theMovedFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFromPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theToPoint);
+
+ /** \brief Move feature using its moved attribute
+ * \param[in] theMovedAttribute dragged point attribute of sketch feature
+ * \param[in] theFromPoint original position of the moved point
+ * \param[in] theToPoint prefereble position (current position of the mouse)
+ * \return \c true if the attribute owner has been changed successfully
+ */
+ bool moveAttribute(const std::shared_ptr<GeomDataAPI_Point2D>& theMovedAttribute,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFromPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theToPoint);
+
/** \brief Removes a constraint from the manager
* \param[in] theConstraint constraint to be removed
* \return \c true if the constraint removed successfully
virtual void addConstraint(ConstraintPtr theConstraint,
ConstraintWrapperPtr theSolverConstraint);
- /// \brief Add list of temporary constraints which will be destroyed
+ /// \brief Add a movement constraint which will be destroyed
/// after the next solving of the set of constraints.
/// \param theSolverConstraint [in] solver's constraint
- virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint) = 0;
+ virtual void addMovementConstraint(const ConstraintWrapperPtr& theSolverConstraint) = 0;
/// \brief Change mapping feature from SketchPlugin and
/// the entity applicable for corresponding solver.
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Collinear::SketcherPrs_Collinear(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Collinear(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Collinear, SketcherPrs_SymbolPrs)
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Equal::SketcherPrs_Equal(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Equal(ModelAPI_Feature* theConstraint,
- const std::shared_ptr<GeomAPI_Ax3>& thePlane);
+ ModelAPI_CompositeFeature* theSketcher,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Equal, SketcherPrs_SymbolPrs)
/// Returns true if the constraint feature arguments are correcly filled to build AIS presentation
// Macros for constraint presentation definition
#define CONSTRAINT_PRS_IMPL(NAME, CLASS) \
AISObjectPtr SketcherPrs_Factory::NAME(ModelAPI_Feature* theConstraint, \
+ ModelAPI_CompositeFeature* theSketcher, \
const std::shared_ptr<GeomAPI_Ax3>& thePlane, \
AISObjectPtr thePrevious) \
{ \
anAISObj = thePrevious; \
else { \
anAISObj = AISObjectPtr(new GeomAPI_AISObject()); \
- Handle(CLASS) aPrs = new CLASS(theConstraint, thePlane); \
+ Handle(CLASS) aPrs = new CLASS(theConstraint, theSketcher, thePlane); \
anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs)); \
} \
} \
return anAISObj; \
}
-CONSTRAINT_PRS_IMPL(coincidentConstraint, SketcherPrs_Coincident);
+
CONSTRAINT_PRS_IMPL(collinearConstraint, SketcherPrs_Collinear);
CONSTRAINT_PRS_IMPL(parallelConstraint, SketcherPrs_Parallel);
CONSTRAINT_PRS_IMPL(perpendicularConstraint, SketcherPrs_Perpendicular);
CONSTRAINT_PRS_IMPL(rigidConstraint, SketcherPrs_Rigid);
CONSTRAINT_PRS_IMPL(equalConstraint, SketcherPrs_Equal);
CONSTRAINT_PRS_IMPL(tangentConstraint, SketcherPrs_Tangent);
-CONSTRAINT_PRS_IMPL(radiusConstraint, SketcherPrs_Radius);
-CONSTRAINT_PRS_IMPL(lengthDimensionConstraint, SketcherPrs_LengthDimension);
CONSTRAINT_PRS_IMPL(middleConstraint, SketcherPrs_Middle);
CONSTRAINT_PRS_IMPL(mirrorConstraint, SketcherPrs_Mirror);
-CONSTRAINT_PRS_IMPL(angleConstraint, SketcherPrs_Angle);
+
+
+
+#define CONSTRAINT2_PRS_IMPL(NAME, CLASS) \
+AISObjectPtr SketcherPrs_Factory::NAME(ModelAPI_Feature* theConstraint, \
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane, \
+ AISObjectPtr thePrevious) \
+{ \
+ std::shared_ptr<GeomAPI_AISObject> anAISObj; \
+ if (CLASS::IsReadyToDisplay(theConstraint, thePlane)) { \
+ if (thePrevious.get()) \
+ anAISObj = thePrevious; \
+ else { \
+ anAISObj = AISObjectPtr(new GeomAPI_AISObject()); \
+ Handle(CLASS) aPrs = new CLASS(theConstraint, thePlane); \
+ anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs)); \
+ } \
+ } \
+ return anAISObj; \
+}
+
+
+CONSTRAINT2_PRS_IMPL(coincidentConstraint, SketcherPrs_Coincident);
+CONSTRAINT2_PRS_IMPL(angleConstraint, SketcherPrs_Angle);
+CONSTRAINT2_PRS_IMPL(radiusConstraint, SketcherPrs_Radius);
+CONSTRAINT2_PRS_IMPL(lengthDimensionConstraint, SketcherPrs_LengthDimension);
// Non-standard constraints definition
AISObjectPtr SketcherPrs_Factory::horisontalConstraint(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
AISObjectPtr thePrevious)
{
else {
anAISObj = AISObjectPtr(new GeomAPI_AISObject());
Handle(SketcherPrs_HVDirection) aPrs =
- new SketcherPrs_HVDirection(theConstraint, thePlane, true);
+ new SketcherPrs_HVDirection(theConstraint, theSketcher, thePlane, true);
anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
}
}
}
AISObjectPtr SketcherPrs_Factory::verticalConstraint(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
AISObjectPtr thePrevious)
{
else {
anAISObj = AISObjectPtr(new GeomAPI_AISObject());
Handle(SketcherPrs_HVDirection) aPrs =
- new SketcherPrs_HVDirection(theConstraint, thePlane, false);
+ new SketcherPrs_HVDirection(theConstraint, theSketcher, thePlane, false);
anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
}
}
}
AISObjectPtr SketcherPrs_Factory::translateConstraint(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
AISObjectPtr thePrevious)
{
else {
anAISObj = AISObjectPtr(new GeomAPI_AISObject());
Handle(SketcherPrs_Transformation) aPrs =
- new SketcherPrs_Transformation(theConstraint, thePlane, true);
+ new SketcherPrs_Transformation(theConstraint, theSketcher, thePlane, true);
anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
}
}
}
AISObjectPtr SketcherPrs_Factory::rotateConstraint(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
AISObjectPtr thePrevious)
{
else {
anAISObj = AISObjectPtr(new GeomAPI_AISObject());
Handle(SketcherPrs_Transformation) aPrs =
- new SketcherPrs_Transformation(theConstraint, thePlane, false);
+ new SketcherPrs_Transformation(theConstraint, theSketcher, thePlane, false);
anAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs));
}
}
#include "SketcherPrs.h"
#include <ModelAPI_Feature.h>
+#include <ModelAPI_CompositeFeature.h>
#include <GeomAPI_Ax3.h>
#include <GeomAPI_AISObject.h>
#define GET_CONSTRAINT_PRS(NAME) \
static AISObjectPtr NAME(ModelAPI_Feature* theConstraint, \
+ ModelAPI_CompositeFeature* theSketcher, \
const std::shared_ptr<GeomAPI_Ax3>& thePlane, \
AISObjectPtr thePrevious);
class SKETCHERPRS_EXPORT SketcherPrs_Factory
{
public:
- /// Creates coincedent constraint presentation
- /// \param theConstraint the constraint
- /// \param thePlane the current sketch plane
- /// \param thePrevious the previous presentation
- GET_CONSTRAINT_PRS(coincidentConstraint)
-
/// Creates collinear constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
/// \param thePrevious the previous presentation
GET_CONSTRAINT_PRS(tangentConstraint)
- /// Creates radius dimension presentation
- /// \param theConstraint the constraint
- /// \param thePlane the current sketch plane
- /// \param thePrevious the previous presentation
- GET_CONSTRAINT_PRS(radiusConstraint)
-
- /// Creates length dimension presentation
- /// \param theConstraint the constraint
- /// \param thePlane the current sketch plane
- /// \param thePrevious the previous presentation
- GET_CONSTRAINT_PRS(lengthDimensionConstraint)
-
/// Creates middle constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
/// \param thePrevious the previous presentation
GET_CONSTRAINT_PRS(rotateConstraint)
+#define GET_CONSTRAINT2_PRS(NAME) \
+ static AISObjectPtr NAME(ModelAPI_Feature* theConstraint, \
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane, \
+ AISObjectPtr thePrevious);
+
+ /// Creates coincedent constraint presentation
+ /// \param theConstraint the constraint
+ /// \param thePlane the current sketch plane
+ /// \param thePrevious the previous presentation
+ GET_CONSTRAINT2_PRS(coincidentConstraint)
+
/// Creates angle constraint presentation
/// \param theConstraint the constraint
/// \param thePlane the current sketch plane
/// \param thePrevious the previous presentation
- GET_CONSTRAINT_PRS(angleConstraint)
+ GET_CONSTRAINT2_PRS(angleConstraint)
+
+ /// Creates length dimension presentation
+ /// \param theConstraint the constraint
+ /// \param thePlane the current sketch plane
+ /// \param thePrevious the previous presentation
+ GET_CONSTRAINT2_PRS(lengthDimensionConstraint)
+
+ /// Creates radius dimension presentation
+ /// \param theConstraint the constraint
+ /// \param thePlane the current sketch plane
+ /// \param thePrevious the previous presentation
+ GET_CONSTRAINT2_PRS(radiusConstraint)
};
#endif
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_HVDirection::SketcherPrs_HVDirection(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
bool isHorisontal)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane), myIsHorisontal(isHorisontal)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane),
+ myIsHorisontal(isHorisontal)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
/// \param isHorisontal a flag horizontal or vertical presentation
Standard_EXPORT SketcherPrs_HVDirection(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
bool isHorisontal);
#include <SketchPlugin_Constraint.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintDistance.h>
+#include <SketchPlugin_ConstraintDistanceHorizontal.h>
+#include <SketchPlugin_ConstraintDistanceVertical.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Circle.h>
#include <AIS_DisplaySpecialSymbol.hxx>
+//#ifdef OCCT_28850_FIXED
/// Creates an aspect to be shown in length/radius dimension presentations
/// \return an instance of aspect
{
SetDimensionAspect(createDimensionAspect());
myStyleListener = new SketcherPrs_DimensionStyleListener();
+
+#ifdef OCCT_28850_FIXED
+ if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
+ SetDirection(true, mySketcherPlane->dirX()->impl<gp_Dir>());
+ else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
+ SetDirection(true, mySketcherPlane->dirY()->impl<gp_Dir>());
+#endif
}
SketcherPrs_LengthDimension::~SketcherPrs_LengthDimension()
thePnt2 = thePlane->to3D(aEndPoint->x(), aEndPoint->y())->impl<gp_Pnt>();
return true;
- } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID()) {
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
// The constraint is distance
std::shared_ptr<GeomDataAPI_Point2D> aPoint_A = SketcherPrs_Tools::getFeaturePoint(
aData, SketchPlugin_Constraint::ENTITY_A(), thePlane);
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Middle::SketcherPrs_Middle(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Middle(ModelAPI_Feature* theConstraint,
- const std::shared_ptr<GeomAPI_Ax3>& thePlane);
+ ModelAPI_CompositeFeature* theSketcher,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Middle, SketcherPrs_SymbolPrs)
/// Returns true if the constraint feature arguments are correcly filled to build AIS presentation
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Mirror::SketcherPrs_Mirror(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Mirror(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Mirror, SketcherPrs_SymbolPrs)
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Parallel::SketcherPrs_Parallel(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Parallel(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Parallel, SketcherPrs_SymbolPrs)
#include <Graphic3d_AspectLine3d.hxx>
#include <Prs3d_Root.hxx>
+#include <GeomAPI_Curve.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Perpendicular, SketcherPrs_SymbolPrs);
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Perpendicular::SketcherPrs_Perpendicular(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
ObjectPtr aObj2 =
SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_B());
+ GeomShapePtr aShp1 = SketcherPrs_Tools::getShape(aObj1);
+ GeomShapePtr aShp2 = SketcherPrs_Tools::getShape(aObj2);
+
+ 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);
+
// Compute position of symbols
SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
- gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
- gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
- myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+ gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep, aPnt);
+ //gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
+ myPntArray = new Graphic3d_ArrayOfPoints(1, withColor);
myPntArray->AddVertex(aP1);
- myPntArray->AddVertex(aP2);
+ //myPntArray->AddVertex(aP2);
return true;
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Perpendicular(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Perpendicular, SketcherPrs_SymbolPrs)
#include <GeomAPI_Curve.h>
#include <GeomAPI_Vertex.h>
#include <GeomAPI_Dir.h>
+#include <GeomAPI_Ax3.h>
+#include <GeomAPI_Circ.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
+
+#include <BRepExtrema_ExtPC.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <Geom_Curve.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <gp_Dir.hxx>
+
+#include <array>
static SketcherPrs_PositionMgr* MyPosMgr = NULL;
+#define PI 3.1415926535897932
+
// The class is implemented as a singlton
SketcherPrs_PositionMgr* SketcherPrs_PositionMgr::get()
{
}
}
-gp_Pnt SketcherPrs_PositionMgr::getPosition(ObjectPtr theShape,
- const SketcherPrs_SymbolPrs* thePrs,
- double theStep)
+
+bool SketcherPrs_PositionMgr::isPntConstraint(const std::string& theName)
+{
+ static std::list<std::string> aConstraints;
+ if (aConstraints.size() == 0) {
+ aConstraints.push_back(SketchPlugin_ConstraintTangent::ID());
+ aConstraints.push_back(SketchPlugin_ConstraintPerpendicular::ID());
+ }
+ std::list<std::string>::const_iterator aIt;
+ for (aIt = aConstraints.cbegin(); aIt != aConstraints.cend(); ++aIt) {
+ if ((*aIt) == theName)
+ return true;
+ }
+ return false;
+}
+
+bool containsPoint(const FeaturePtr& theFeature, GeomPnt2dPtr thePnt2d, GeomPointPtr thePos)
+{
+ if (theFeature->getKind() == SketchPlugin_Line::ID()) {
+ AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->data()->attribute(SketchPlugin_Line::START_ID()));
+ AttributePoint2DPtr aSPnt2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->data()->attribute(SketchPlugin_Line::END_ID()));
+
+ GeomPnt2dPtr aPnt1 = aSPnt1->pnt();
+ GeomPnt2dPtr aPnt2 = aSPnt2->pnt();
+
+ if (aPnt1->isEqual(thePnt2d) || aPnt2->isEqual(thePnt2d))
+ return true;
+ } else if ((theFeature->getKind() == SketchPlugin_Circle::ID()) ||
+ (theFeature->getKind() == SketchPlugin_Arc::ID())) {
+ GeomCurvePtr aCurve;
+ ObjectPtr aResObj;
+ std::list<ResultPtr> aResults = theFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+ GeomShapePtr aShp = SketcherPrs_Tools::getShape((*aIt));
+ if (aShp->isEdge()) {
+ aResObj = (*aIt);
+ aCurve = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp));
+ break;
+ }
+ }
+ if (aCurve.get()) {
+ double aStart = aCurve->startParam();
+ double aEnd = aCurve->endParam();
+ GeomCirclePtr aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
+ double aParam;
+ if (aCircle->parameter(thePos, 1.e-4, aParam) && (aParam >= aStart) && (aParam <= aEnd))
+ return true;
+ }
+ }
+ return false;
+}
+
+const std::array<int, 2>& SketcherPrs_PositionMgr::getPositionIndex(GeomPointPtr thePos,
+ const SketcherPrs_SymbolPrs* thePrs)
{
+ if (myPntShapes.count(thePrs->feature()) == 0) {
+ // Renumerate positions around the specified constraint point for all constraints
+ GeomAx3Ptr aAx3 = thePrs->plane();
+ ModelAPI_CompositeFeature* aOwner = thePrs->sketcher();
+ GeomPnt2dPtr aPnt2d = thePos->to2D(aAx3->origin(), aAx3->dirX(), aAx3->dirY());
+
+ int aNbSubs = aOwner->numberOfSubs();
+ int aId = 0;
+ std::list<const ModelAPI_Feature*> aFeaList;
+ for (int i = 0; i < aNbSubs; i++) {
+ FeaturePtr aFeature = aOwner->subFeature(i);
+
+ if (myPntShapes.count(aFeature.get()) == 1) {
+ myPntShapes[aFeature.get()][0] = aId;
+ aId++;
+ aFeaList.push_back(aFeature.get());
+ } else {
+ if (isPntConstraint(aFeature->getKind())) {
+ DataPtr aData = aFeature->data();
+ AttributeRefAttrPtr aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+ FeaturePtr aObj = ModelAPI_Feature::feature(aObjRef->object());
+ bool aContains = false;
+ if (containsPoint(aObj, aPnt2d, thePos)) {
+ aContains = true;
+ } else {
+ aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
+ aObj = ModelAPI_Feature::feature(aObjRef->object());
+ if (containsPoint(aObj, aPnt2d, thePos)) {
+ aContains = true;
+ }
+ }
+ if (aContains) {
+ myPntShapes[aFeature.get()][0] = aId;
+ aId++;
+ aFeaList.push_back(aFeature.get());
+ }
+ }
+ }
+ }
+ int aSize = (int) aFeaList.size();
+ std::list<const ModelAPI_Feature*>::const_iterator aIt;
+ for (aIt = aFeaList.cbegin(); aIt != aFeaList.cend(); aIt++) {
+ myPntShapes[*aIt][1] = aSize;
+ }
+ }
+ return myPntShapes[thePrs->feature()];
+}
+
+//*****************************************************************
+gp_Vec getVector(ObjectPtr theShape, GeomDirPtr theDir, gp_Pnt theP)
+{
+ gp_Vec aVec;
std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(theShape);
- gp_Pnt aP; // Central point
- gp_Vec aVec1; // main vector
if (aShape->isEdge()) {
std::shared_ptr<GeomAPI_Curve> aCurve =
std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShape));
- std::shared_ptr<GeomAPI_Pnt> aPnt1; // Start point of main vector
- std::shared_ptr<GeomAPI_Pnt> aPnt2; // End point of main vector
- if (aCurve->isLine()) {
- std::shared_ptr<GeomAPI_Edge> aEdge =
- std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aShape));
- aPnt1 = aEdge->firstPoint();
- aPnt2 = aEdge->lastPoint();
+ if (aCurve->isCircle()) {
+ GeomEdgePtr aEdgePtr(new GeomAPI_Edge(aShape));
+ GeomVertexPtr aVertexPtr(new GeomAPI_Vertex(theP.X(), theP.Y(), theP.Z()));
+ BRepExtrema_ExtPC aExtrema(aVertexPtr->impl<TopoDS_Vertex>(),
+ aEdgePtr->impl<TopoDS_Edge>());
+ int aNb = aExtrema.NbExt();
+ if (aNb > 0) {
+ for (int i = 1; i <= aNb; i++) {
+ if (aExtrema.IsMin(i)) {
+ double aParam = aExtrema.Parameter(i);
+ Handle(Geom_Curve) aCurv = aCurve->impl<Handle_Geom_Curve>();
+ gp_Pnt aP;
+ aCurv->D1(aParam, aP, aVec);
+ break;
+ }
+ }
+ }
+ } else {
+ GeomPointPtr aPnt1 = aCurve->getPoint(aCurve->endParam());
+ GeomPointPtr aPnt2 = aCurve->getPoint(aCurve->startParam());
- // Find the middle point
- aP = gp_Pnt((aPnt1->x() + aPnt2->x())/2.,
- (aPnt1->y() + aPnt2->y())/2.,
- (aPnt1->z() + aPnt2->z())/2.);
+ gp_Pnt aPn2 = aPnt2->impl<gp_Pnt>();
+ if (aPn2.IsEqual(theP, Precision::Confusion()))
+ aVec = gp_Vec(aPn2, aPnt1->impl<gp_Pnt>());
+ else
+ aVec = gp_Vec(aPnt1->impl<gp_Pnt>(), aPn2);
+ }
+ } else {
+ aVec = gp_Vec(theDir->impl<gp_Dir>());
+ }
+ return aVec;
+}
- } else {
+//*****************************************************************
+gp_Pnt SketcherPrs_PositionMgr::getPosition(ObjectPtr theShape,
+ const SketcherPrs_SymbolPrs* thePrs,
+ double theStep, GeomPointPtr thePnt)
+{
+ std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(theShape);
+ gp_Pnt aP; // Central point
+
+ if (thePnt.get()) {
+ return getPointPosition(theShape, thePrs, theStep, thePnt);
+ } else {
+ if (aShape->isEdge()) {
+ std::shared_ptr<GeomAPI_Curve> aCurve =
+ std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShape));
// this is a circle or arc
double aMidParam = (aCurve->startParam() + aCurve->endParam()) / 2.;
std::shared_ptr<GeomAPI_Pnt> aPnt = aCurve->getPoint(aMidParam);
aP = aPnt->impl<gp_Pnt>();
-
- aPnt1 = aCurve->getPoint((aMidParam + aCurve->endParam()) / 2.);
- aPnt2 = aCurve->getPoint((aMidParam + aCurve->startParam()) / 2.);
+ } else {
+ // This is a point
+ std::shared_ptr<GeomAPI_Vertex> aVertex =
+ std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aShape));
+ std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
+ aP = aPnt->impl<gp_Pnt>();
}
- aVec1 = gp_Vec(aPnt1->impl<gp_Pnt>(), aPnt2->impl<gp_Pnt>());
- } else {
- // This is a point
- std::shared_ptr<GeomAPI_Vertex> aVertex =
- std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aShape));
- std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
- aP = aPnt->impl<gp_Pnt>();
-
- std::shared_ptr<GeomAPI_Dir> aDir = thePrs->plane()->dirX();
- aVec1 = gp_Vec(aDir->impl<gp_Dir>());
}
+ // main vector
+ gp_Vec aVec1 = getVector(theShape, thePrs->plane()->dirX(), aP);
+
// Compute shifting vector for a one symbol
gp_Vec aShift = aVec1.Crossed(thePrs->plane()->normal()->impl<gp_Dir>());
aShift.Normalize();
return aP;
}
+
+//*****************************************************************
+//! Returns curves connected to the given point
+std::list<ObjectPtr> getCurves(const GeomPointPtr& thePnt, const SketcherPrs_SymbolPrs* thePrs)
+{
+ std::list<ObjectPtr> aList;
+ GeomAx3Ptr aAx3 = thePrs->plane();
+ ModelAPI_CompositeFeature* aOwner = thePrs->sketcher();
+ GeomPnt2dPtr aPnt2d = thePnt->to2D(aAx3->origin(), aAx3->dirX(), aAx3->dirY());
+
+ int aNbSubs = aOwner->numberOfSubs();
+ for (int i = 0; i < aNbSubs; i++) {
+ FeaturePtr aFeature = aOwner->subFeature(i);
+ if (!aFeature->firstResult().get()) // There is no result
+ continue;
+
+ if (aFeature->getKind() == SketchPlugin_Line::ID()) {
+ AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->data()->attribute(SketchPlugin_Line::START_ID()));
+ AttributePoint2DPtr aSPnt2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->data()->attribute(SketchPlugin_Line::END_ID()));
+
+ GeomPnt2dPtr aPnt1 = aSPnt1->pnt();
+ GeomPnt2dPtr aPnt2 = aSPnt2->pnt();
+
+ if (aPnt1->isEqual(aPnt2d) || aPnt2->isEqual(aPnt2d)) {
+ GeomShapePtr aShp = SketcherPrs_Tools::getShape(aFeature->firstResult());
+ GeomCurvePtr aCurv = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp));
+ aList.push_back(aFeature->firstResult());
+ }
+ } else if ((aFeature->getKind() == SketchPlugin_Circle::ID()) ||
+ (aFeature->getKind() == SketchPlugin_Arc::ID())) {
+ GeomCurvePtr aCurve;
+ ObjectPtr aResObj;
+ std::list<ResultPtr> aResults = aFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+ GeomShapePtr aShp = SketcherPrs_Tools::getShape((*aIt));
+ if (aShp->isEdge()) {
+ aResObj = (*aIt);
+ aCurve = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp));
+ break;
+ }
+ }
+ if (aCurve.get()) {
+ double aStart = aCurve->startParam();
+ double aEnd = aCurve->endParam();
+ GeomCirclePtr aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
+ double aParam;
+ if (aCircle->parameter(thePnt, 1.e-4, aParam) && (aParam >= aStart) && (aParam <= aEnd))
+ aList.push_back(aResObj);
+ }
+ }
+ }
+ return aList;
+}
+
+//*****************************************************************
+gp_Pnt SketcherPrs_PositionMgr::getPointPosition(
+ ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
+ double theStep, GeomPointPtr thePnt)
+{
+ gp_Pnt aP = thePnt->impl<gp_Pnt>();
+ GeomDirPtr aNormal = thePrs->plane()->normal();
+ gp_Dir aNormDir = aNormal->impl<gp_Dir>();
+
+ std::list<ObjectPtr> aCurves = getCurves(thePnt, thePrs);
+ std::list<ObjectPtr>::const_iterator aItCurv;
+ std::list<gp_Vec> aVectorsList;
+ // Calculate all vectors
+ for (aItCurv = aCurves.cbegin(); aItCurv != aCurves.cend(); aItCurv++) {
+ aVectorsList.push_back(getVector((*aItCurv), thePrs->plane()->dirX(), aP));
+ }
+
+ // Position of the symbol
+ const std::array<int, 2>& aPos = getPositionIndex(thePnt, thePrs);
+
+ // Angle size of a symbol
+ double aAngleStep = PI * 50./180.;
+
+ std::list<gp_Vec>::const_iterator aItVec;
+ std::list<double> aAngles;
+ std::list<gp_Vec> aVectors;
+ // Select closest vectors and calculate angles between base vector and closest vector
+ for (aItVec = aVectorsList.cbegin(); aItVec != aVectorsList.cend(); aItVec++) {
+ std::list<gp_Vec>::const_iterator aIt;
+ double aMinAng = 0;
+ gp_Vec aVec = *aItVec;
+ for (aIt = aVectorsList.cbegin(); aIt != aVectorsList.cend(); aIt++) {
+ double aAng = aVec.AngleWithRef(*aIt, aNormDir);
+ if (aAng != 0) {
+ if (aAng < 0)
+ aAng = 2 * PI + aAng;
+
+ if (aMinAng == 0)
+ aMinAng = aAng;
+ else if (aAng < aMinAng) {
+ aMinAng = aAng;
+ }
+ }
+ }
+ aVectors.push_back(aVec);
+ aAngles.push_back(aMinAng);
+ }
+
+ int aPosCount = 0;
+ double aAng;
+ std::list<double>::const_iterator aItAng;
+
+ double aAngPos;
+ gp_Vec aVecPos;
+ bool aHasPlace = false;
+ int aIntId = 0; // a position inside a one sector
+ while (aPosCount < aPos[1]) {
+ for (aItAng = aAngles.cbegin(), aItVec = aVectors.cbegin();
+ aItAng != aAngles.cend(); ++aItAng, ++aItVec) {
+ aAng = (*aItAng);
+ int Nb = int(aAng / aAngleStep);
+ aPosCount += Nb;
+
+ if ((!aHasPlace) && (aPosCount >= (aPos[0] + 1))) {
+ aHasPlace = true;
+ aAngPos = (*aItAng);
+ aVecPos = (*aItVec);
+ aIntId = aPos[0] - (aPosCount - Nb);
+ }
+ }
+ if (aPosCount < aPos[1]) {
+ aAngleStep -= 0.1;
+ aHasPlace = false;
+ aPosCount = 0;
+ }
+ }
+
+ gp_Ax1 aRotAx(aP, aNormDir);
+ if (aHasPlace) {
+ // rotate base vector on a necessary angle
+ gp_Vec aShift = aVecPos.Rotated(aRotAx, aAngleStep + aAngleStep * aIntId);
+ aShift.Normalize();
+ aShift.Multiply(theStep * 1.5);
+ return aP.Translated(aShift);
+ }
+ return aP;
+}
+
+//*****************************************************************
void SketcherPrs_PositionMgr::deleteConstraint(const SketcherPrs_SymbolPrs* thePrs)
{
std::map<ObjectPtr, PositionsMap>::iterator aIt;
#include "SketcherPrs_SymbolPrs.h"
#include <GeomAPI_Shape.h>
+#include <GeomAPI_Pnt.h>
#include <gp_Pnt.hxx>
#include <ModelAPI_Object.h>
#include <map>
+#include <array>
/**
* \ingroup GUI
/// \param theLine constrained object
/// \param thePrs a presentation of constraint
/// \param theStep step between symbols
- gp_Pnt getPosition(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs, double theStep = 20);
+ gp_Pnt getPosition(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
+ double theStep = 20, GeomPointPtr thePnt = GeomPointPtr());
/// Deletes constraint object from internal structures. Has to be called on constraint delete.
/// \param thePrs a constraint presentation
/// \param thePrs a presentation of constraint
int getPositionIndex(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs);
+ /// Returns position index of the given constraint around a point
+ /// \param theLine constrained object
+ /// \param thePrs a presentation of constraint
+ const std::array<int, 2>& getPositionIndex(GeomPointPtr thePos,
+ const SketcherPrs_SymbolPrs* thePrs);
+
+ /// Returns position of a constraint around a point
+ /// \param theLine a base object of the constraint
+ /// \param thePrs a presentation of the constraint symbol
+ /// \param theStep step from base point
+ /// \param thePnt a base point
+ gp_Pnt getPointPosition(ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
+ double theStep, GeomPointPtr thePnt);
+
+ static bool isPntConstraint(const std::string& theName);
+
private:
typedef std::map<const SketcherPrs_SymbolPrs*, int> PositionsMap;
+ typedef std::map<const ModelAPI_Feature*, std::array<int, 2>> FeaturesMap;
/// The map which contains position of presentation
PositionsMap myIndexes;
/// The map contains position index
std::map<ObjectPtr, PositionsMap> myShapes;
+
+ /// The map contains position of index for constraints around a point
+ FeaturesMap myPntShapes;
};
#endif
\ No newline at end of file
SketcherPrs_Rigid::SketcherPrs_Rigid(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Rigid(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
#include <GeomAPI_Vertex.h>
#include <GeomAPI_Curve.h>
+#include <ModelAPI_Tools.h>
+
#include <Events_InfoMessage.h>
#include <Graphic3d_ArrayOfSegments.hxx>
SketcherPrs_SymbolPrs::SketcherPrs_SymbolPrs(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : AIS_InteractiveObject(), myConstraint(theConstraint), myPlane(thePlane), myIsCustomColor(false)
+ : AIS_InteractiveObject(), myConstraint(theConstraint),
+ myPlane(thePlane), myIsCustomColor(false),
+ mySketcher(theSketcher)
{
SetAutoHilight(Standard_False);
}
theBndBox.Update (aTmpBox.CornerMin().x(), aTmpBox.CornerMin().y(), aTmpBox.CornerMin().z(),
aTmpBox.CornerMax().x(), aTmpBox.CornerMax().y(), aTmpBox.CornerMax().z());
}
-
#include "SketcherPrs_SensitivePoint.h"
#include <ModelAPI_Feature.h>
#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_CompositeFeature.h>
#include <AIS_InteractiveObject.hxx>
#include <GeomAPI_Ax3.h>
/// \param theConstraint a constraint feature
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_SymbolPrs(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
virtual ~SketcherPrs_SymbolPrs();
/// Returns feature object
Standard_EXPORT ModelAPI_Feature* feature() const { return myConstraint; }
+ /// Returns Sketcher object (owner of the constraint)
+ Standard_EXPORT ModelAPI_CompositeFeature* sketcher() const { return mySketcher; }
+
/// Return array of points where symbols will be placed
const Handle(Graphic3d_ArrayOfPoints)& pointsArray() const { return myPntArray; }
/// Constraint feature
ModelAPI_Feature* myConstraint;
+ /// Sketcher feature
+ ModelAPI_CompositeFeature* mySketcher;
+
/// Plane of the current sketcher
std::shared_ptr<GeomAPI_Ax3> myPlane;
#include "SketcherPrs_PositionMgr.h"
#include <GeomAPI_Curve.h>
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Lin.h>
#include <SketchPlugin_Constraint.h>
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Tangent::SketcherPrs_Tangent(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane)
{
}
ObjectPtr aObj2 =
SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_B());
+ GeomShapePtr aShp1 = SketcherPrs_Tools::getShape(aObj1);
+ GeomShapePtr aShp2 = SketcherPrs_Tools::getShape(aObj2);
+
+ GeomCurvePtr aCurv1 = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp1));
+ GeomCurvePtr aCurv2 = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp2));
+
+ GeomCurvePtr aLine;
+ GeomCirclePtr aCircle;
+ double aFirst, aLast;
+ if (aCurv1->isLine()) {
+ aLine = aCurv1;
+ aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurv2));
+ aFirst = aCurv2->startParam();
+ aLast = aCurv2->endParam();
+ } else {
+ aLine = aCurv2;
+ aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurv1));
+ aFirst = aCurv1->startParam();
+ aLast = aCurv1->endParam();
+ }
+
+ GeomPointPtr aPnt1 = aLine->getPoint(aLine->startParam());
+ GeomPointPtr aPnt2 = aLine->getPoint(aLine->endParam());
+ double aParam;
+ GeomPointPtr aPnt;
+ if (aCircle->parameter(aPnt1, 1.e-4, aParam) && (aParam >= aFirst) && (aParam <= aLast))
+ aPnt = aPnt1;
+ else if (aCircle->parameter(aPnt2, 1.e-4, aParam) && (aParam >= aFirst) && (aParam <= aLast))
+ aPnt = aPnt2;
+
// Compute points coordinates
- SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
- gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
- gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
- myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
- myPntArray->AddVertex(aP1);
- myPntArray->AddVertex(aP2);
+ if (aPnt.get()) {
+ SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+ gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep, aPnt);
+ myPntArray = new Graphic3d_ArrayOfPoints(1, withColor);
+ myPntArray->AddVertex(aP1);
+ } else {
+ SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+ gp_Pnt aP1 = aMgr->getPosition(aObj1, this, theStep);
+ gp_Pnt aP2 = aMgr->getPosition(aObj2, this, theStep);
+ myPntArray = new Graphic3d_ArrayOfPoints(2, withColor);
+ myPntArray->AddVertex(aP1);
+ myPntArray->AddVertex(aP2);
+ }
return true;
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
Standard_EXPORT SketcherPrs_Tangent(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
DEFINE_STANDARD_RTTIEXT(SketcherPrs_Tangent, SketcherPrs_SymbolPrs)
static Handle(Image_AlienPixMap) MyPixMap;
SketcherPrs_Transformation::SketcherPrs_Transformation(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
bool isTranslation)
- : SketcherPrs_SymbolPrs(theConstraint, thePlane), myIsTranslation(isTranslation)
+ : SketcherPrs_SymbolPrs(theConstraint, theSketcher, thePlane), myIsTranslation(isTranslation)
{
}
public:
/// Constructor
/// \param theConstraint a constraint feature
+ /// \param theSketcher a sketcher object
/// \param thePlane a coordinate plane of current sketch
/// \param isTranslation a flag is it translation or rotation
Standard_EXPORT SketcherPrs_Transformation(ModelAPI_Feature* theConstraint,
+ ModelAPI_CompositeFeature* theSketcher,
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
bool isTranslation);
bool aIsRoot = false;
foreach(QModelIndex aIdx, aSelectedIndexes) {
// Process only first column
- if (aIdx.column() == 0) {
+ if (aIdx.column() == 1) {
aIsRoot = !aIdx.parent().isValid();
// Exit if the selected index belongs to non active document
if (aIsRoot && (aActiveDoc != aMgr->moduleDocument()))
//
#include "XGUI_DataModel.h"
+#include "XGUI_Workshop.h"
+#include "XGUI_ObjectsBrowser.h"
+#include "XGUI_Displayer.h"
#include <ModuleBase_IconFactory.h>
XGUI_DataModel::XGUI_DataModel(QObject* theParent) : QAbstractItemModel(theParent)//,
//myIsEventsProcessingBlocked(false)
{
+ XGUI_ObjectsBrowser* aOB = qobject_cast<XGUI_ObjectsBrowser*>(theParent);
+ myWorkshop = aOB->workshop();
+
Events_Loop* aLoop = Events_Loop::loop();
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
}
} else {
// Object created in sub-document
- QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get());
+ QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
if (aDocRoot.isValid()) {
// Check that new folders could appear
QStringList aNotEmptyFolders = listOfShowNotEmptyFolders(false);
}
} else {
// Remove row for sub-document
- QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get());
+ QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
if (aDocRoot.isValid()) {
int aRow = aDoc->size(aGroup);
int aNbSubFolders = foldersCount(aDoc.get());
&& (aFeature->firstResult()->groupName() == ModelAPI_ResultField::group())) {
ResultFieldPtr aResult =
std::dynamic_pointer_cast<ModelAPI_ResultField>(aFeature->firstResult());
- QModelIndex aIndex = objectIndex(aResult);
+ QModelIndex aIndex = objectIndex(aResult, 0);
removeRows(0, aResult->stepsSize(), aIndex);
} else {
- QModelIndex aIndex = objectIndex(aObject);
+ QModelIndex aIndex = objectIndex(aObject, 0);
if (aIndex.isValid()) {
emit dataChanged(aIndex, aIndex);
}
// Update a sub-document
if (aGroup == myXMLReader->subType()) {
// Update sub-document root
- aParent = findDocumentRootIndex(aDoc.get());
+ aParent = findDocumentRootIndex(aDoc.get(), 0);
aStartId = foldersCount(aDoc.get());
} else
// update folder in sub-document
} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
DocumentPtr aDoc = ModelAPI_Session::get()->activeDocument();
if (aDoc != aRootDoc) {
- QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get());
+ QModelIndex aDocRoot = findDocumentRootIndex(aDoc.get(), 0);
if (aDocRoot.isValid())
emit dataChanged(aDocRoot, aDocRoot);
else
}
//******************************************************
-QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject) const
+QModelIndex XGUI_DataModel::objectIndex(const ObjectPtr theObject, int theColumn) const
{
std::string aType = theObject->groupName();
DocumentPtr aDoc = theObject->document();
if (aRow == -1)
return QModelIndex();
else
- return createIndex(aRow, 0, theObject.get());
+ return createIndex(aRow, theColumn, theObject.get());
}
SessionPtr aSession = ModelAPI_Session::get();
DocumentPtr aRootDoc = aSession->moduleDocument();
// The object from sub document
aRow += foldersCount(aDoc.get());
}
- return createIndex(aRow, 0, theObject.get());
+ return createIndex(aRow, theColumn, theObject.get());
}
//******************************************************
int aNbFolders = foldersCount();
int theIndexRow = theIndex.row();
- if ((theRole == Qt::DecorationRole) && (theIndex == lastHistoryIndex()))
- return QIcon(":pictures/arrow.png");
+ if (theRole == Qt::DecorationRole) {
+ if (theIndex == lastHistoryIndex())
+ return QIcon(":pictures/arrow.png");
+ else if (theIndex.column() == 0) {
+ VisibilityState aState = getVisibilityState(theIndex);
+ switch (aState) {
+ case NoneState:
+ return QIcon();
+ case Visible:
+ return QIcon(":pictures/eyeopen.png");
+ case SemiVisible:
+ return QIcon(":pictures/eyemiclosed.png");
+ case Hidden:
+ return QIcon(":pictures/eyeclosed.png");
+ }
+ }
+ }
- if (theIndex.column() == 1)
+ //if (theIndex.column() == 1)
+ if (theIndex.column() != 1)
return QVariant();
quintptr aParentId = theIndex.internalId();
//******************************************************
int XGUI_DataModel::columnCount(const QModelIndex& theParent) const
{
- return 2;
+ return 3;
}
//******************************************************
int aObjId = theRow - aNbFolders;
if (aObjId < aRootDoc->size(aType)) {
ObjectPtr aObj = aRootDoc->object(aType, aObjId);
- aIndex = objectIndex(aObj);
+ aIndex = objectIndex(aObj, theColumn);
}
}
} else {
std::string aType = myXMLReader->rootFolderType(aParentPos);
if (theRow < aRootDoc->size(aType)) {
ObjectPtr aObj = aRootDoc->object(aType, theRow);
- aIndex = objectIndex(aObj);
+ aIndex = objectIndex(aObj, theColumn);
}
} else {
// It is an object which could have children
std::string aType = myXMLReader->subFolderType(aParentRow);
if (theRow < aDoc->size(aType)) {
ObjectPtr aObj = aDoc->object(aType, theRow);
- aIndex = objectIndex(aObj);
+ aIndex = objectIndex(aObj, theColumn);
}
}
} else {
// this is an object under sub document root
std::string aType = myXMLReader->subType();
ObjectPtr aObj = aSubDoc->object(aType, theRow - aNbSubFolders);
- aIndex = objectIndex(aObj);
+ aIndex = objectIndex(aObj, theColumn);
}
} else {
// Check for composite object
ModelAPI_CompositeFeature* aCompFeature =
dynamic_cast<ModelAPI_CompositeFeature*>(aParentObj);
if (aCompFeature) {
- aIndex = objectIndex(aCompFeature->subFeature(theRow));
+ aIndex = objectIndex(aCompFeature->subFeature(theRow), theColumn);
} else {
ModelAPI_ResultCompSolid* aCompRes =
dynamic_cast<ModelAPI_ResultCompSolid*>(aParentObj);
if (aCompRes)
- aIndex = objectIndex(aCompRes->subResult(theRow));
+ aIndex = objectIndex(aCompRes->subResult(theRow), theColumn);
else {
ModelAPI_ResultField* aFieldRes =
dynamic_cast<ModelAPI_ResultField*>(aParentObj);
if (aFieldRes) {
- aIndex = createIndex(theRow, 0, aFieldRes->step(theRow));
+ aIndex = createIndex(theRow, theColumn, aFieldRes->step(theRow));
}
}
}
}
}
}
- if (theColumn != 0)
- return createIndex(aIndex.row(), theColumn, aIndex.internalPointer());
return aIndex;
}
// return first level of folder index
int aFolderId = myXMLReader->rootFolderId(aType);
// Items in a one row must have the same parent
- return createIndex(aFolderId, 0, (void*)Q_NULLPTR);
+ return createIndex(aFolderId, 1, (void*)Q_NULLPTR);
}
} else {
if (aType == myXMLReader->subType())
// return first level of folder index
int aFolderId = folderId(aType, aSubDoc.get());
// Items in a one row must have the same parent
- return createIndex(aFolderId, 0, aSubDoc.get());
+ return createIndex(aFolderId, 1, aSubDoc.get());
}
}
}
if (aObj) {
// An object
if (aObj->isDisabled())
- return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
+ return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
if (aSession->moduleDocument() != aObj->document())
if (aActiveDoc != aObj->document())
- return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
+ return theIndex.column() == 2? Qt::ItemIsSelectable : aNullFlag;
bool isCompositeSub = false;
- // An object which is sub-object of a composite object can not be accessible in column 1
- if (theIndex.column() == 1) {
+ // An object which is sub-object of a composite object can not be accessible in column 2
+ if (theIndex.column() == 2) {
ObjectPtr aObjPtr = aObj->data()->owner();
FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjPtr);
if (aFeature.get()) {
}
//******************************************************
-QModelIndex XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc) const
+QModelIndex
+ XGUI_DataModel::findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn) const
{
SessionPtr aSession = ModelAPI_Session::get();
DocumentPtr aRootDoc = aSession->moduleDocument();
if (myXMLReader->rootType() == ModelAPI_Feature::group()) {
aRow += foldersCount();
}
- return createIndex(aRow, 0, aObj.get());
+ return createIndex(aRow, aColumn, aObj.get());
}
}
} else { // If document is attached to feature
int aRow = i;
if (myXMLReader->rootType() == ModelAPI_Feature::group())
aRow += foldersCount();
- return createIndex(aRow, 0, aObj.get());
+ return createIndex(aRow, aColumn, aObj.get());
}
}
}
}
//******************************************************
-QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc) const
+QModelIndex XGUI_DataModel::documentRootIndex(DocumentPtr theDoc, int theColumn) const
{
SessionPtr aSession = ModelAPI_Session::get();
DocumentPtr aRootDoc = aSession->moduleDocument();
if (theDoc == aRootDoc)
return QModelIndex();
else
- return findDocumentRootIndex(theDoc.get());
+ return findDocumentRootIndex(theDoc.get(), theColumn);
}
//******************************************************
FeaturePtr aFeature = aCurDoc->currentFeature(true);
if (aFeature.get()) {
QModelIndex aInd = objectIndex(aFeature);
- return createIndex(aInd.row(), 1, aInd.internalPointer());
+ return createIndex(aInd.row(), 2, aInd.internalPointer());
} else {
if (aCurDoc == aSession->moduleDocument())
- return createIndex(foldersCount() - 1, 1, -1);
+ return createIndex(foldersCount() - 1, 2, -1);
else
- return createIndex(foldersCount(aCurDoc.get()) - 1, 1, aCurDoc.get());
+ return createIndex(foldersCount(aCurDoc.get()) - 1, 2, aCurDoc.get());
}
}
// myIsEventsProcessingBlocked = theState;
// return aPreviousState;
//}
+
+//******************************************************
+XGUI_DataModel::VisibilityState
+ XGUI_DataModel::getVisibilityState(const QModelIndex& theIndex) const
+{
+ Qt::ItemFlags aFlags = theIndex.flags();
+ if (aFlags == Qt::ItemFlags())
+ return NoneState;
+
+ ObjectPtr aObj = object(theIndex);
+ if (aObj.get()) {
+ ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ if (aResObj.get()) {
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aResObj);
+ if (aCompRes.get()) {
+ VisibilityState aState = aCompRes->numberOfSubs(true) == 0 ?
+ (aDisplayer->isVisible(aCompRes)? Visible : Hidden) : NoneState;
+ for (int i = 0; i < aCompRes->numberOfSubs(true); i++) {
+ ResultPtr aSubRes = aCompRes->subResult(i, true);
+ VisibilityState aS = aDisplayer->isVisible(aSubRes)? Visible : Hidden;
+ if (aState == NoneState)
+ aState = aS;
+ else if (aState != aS) {
+ aState = SemiVisible;
+ break;
+ }
+ }
+ return aState;
+ } else {
+ if (aDisplayer->isVisible(aResObj))
+ return Visible;
+ else
+ return Hidden;
+ }
+ }
+ }
+ return NoneState;
+}
#include <QAbstractItemModel>
class Config_DataModelReader;
+class XGUI_Workshop;
/**\class XGUI_DataModel
* \ingroup GUI
//! Returns index of the object
//! \param theObject object to find
- virtual QModelIndex objectIndex(const ObjectPtr theObject) const;
+ virtual QModelIndex objectIndex(const ObjectPtr theObject, int theColumn = 1) const;
//! Clear internal data
virtual void clear();
/// Returns an index which is root of the given document
/// \param theDoc a document
- QModelIndex documentRootIndex(DocumentPtr theDoc) const;
+ QModelIndex documentRootIndex(DocumentPtr theDoc, int theColumn = 1) const;
/// Returns last history object index
virtual QModelIndex lastHistoryIndex() const;
void treeRebuilt();
private:
+ enum VisibilityState {
+ NoneState,
+ Visible,
+ SemiVisible,
+ Hidden };
+
/// Find a root index which contains objects of the given document
/// \param theDoc the document object
- QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc) const;
+ QModelIndex findDocumentRootIndex(const ModelAPI_Document* theDoc, int aColumn = 1) const;
/// Returns number of folders in document.
/// Considered folders which has to be shown only if they are not empty.
/// \param theParent - index of parent folder
void rebuildBranch(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
-
/// Returns list of folders types which can not be shown empty
/// \param fromRoot - root document flag
QStringList listOfShowNotEmptyFolders(bool fromRoot = true) const;
+ VisibilityState getVisibilityState(const QModelIndex& theIndex) const;
+
Config_DataModelReader* myXMLReader;
+ XGUI_Workshop* myWorkshop;
//bool myIsEventsProcessingBlocked;
};
#include <QStyledItemDelegate>
#include <QMessageBox>
+#ifdef DEBUG_INDXES
+#include <QToolTip>
+#endif
/// Width of second column (minimum acceptable = 27)
+#define FIRST_COL_WIDTH 20
#define SECOND_COL_WIDTH 30
: QTreeView(theParent)
{
setHeaderHidden(true);
+ setTreePosition(1);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
- setItemDelegateForColumn(0, new XGUI_TreeViewItemDelegate(this));
+ setItemDelegateForColumn(1, new XGUI_TreeViewItemDelegate(this));
connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
SLOT(onDoubleClick(const QModelIndex&)));
QTreeView::resizeEvent(theEvent);
QSize aSize = theEvent->size();
if (aSize.isValid()) {
- setColumnWidth(0, aSize.width() - SECOND_COL_WIDTH - 7);
- setColumnWidth(1, SECOND_COL_WIDTH);
+ setColumnWidth(0, FIRST_COL_WIDTH);
+ setColumnWidth(1, aSize.width() - SECOND_COL_WIDTH - FIRST_COL_WIDTH - 10);
+ setColumnWidth(2, SECOND_COL_WIDTH);
}
}
-void XGUI_DataTree::onDoubleClick(const QModelIndex& theIndex)
+#ifdef DEBUG_INDXES
+void XGUI_DataTree::mousePressEvent(QMouseEvent* theEvent)
{
- if (theIndex.column() != 1)
+ QTreeView::mousePressEvent(theEvent);
+ if (theEvent->button() != Qt::MidButton)
return;
+ QModelIndex aInd = indexAt(theEvent->pos());
+ QString aTxt =
+ QString("r=%1 c=%2 p=%3").arg(aInd.row()).arg(aInd.column()).arg((long)aInd.internalPointer());
+
+ QModelIndex aPar = aInd.parent();
+ QString aTxt1 =
+ QString("r=%1 c=%2 p=%3").arg(aPar.row()).arg(aPar.column()).arg((long)aPar.internalPointer());
+ QToolTip::showText(theEvent->globalPos(), aTxt + '\n' + aTxt1);
+}
+#endif
+
+void XGUI_DataTree::mouseReleaseEvent(QMouseEvent* theEvent)
+{
+ QTreeView::mouseReleaseEvent(theEvent);
+#ifdef DEBUG_INDXES
+ if (theEvent->button() != Qt::MidButton)
+ return;
+ QToolTip::hideText();
+#endif
+ if (theEvent->button() == Qt::LeftButton) {
+ QModelIndex aInd = indexAt(theEvent->pos());
+ if (aInd.column() == 0)
+ processEyeClick(aInd);
+ }
+}
+
+void XGUI_DataTree::processHistoryChange(const QModelIndex& theIndex)
+{
SessionPtr aMgr = ModelAPI_Session::get();
// When operation is opened then we can not change history
if (aMgr->isOperation())
for (int i = 0; i < aSize; i++) {
update(aModel->index(i, 0, aParent));
update(aModel->index(i, 1, aParent));
+ update(aModel->index(i, 2, aParent));
+ }
+}
+
+void XGUI_DataTree::processEyeClick(const QModelIndex& theIndex)
+{
+ XGUI_DataModel* aModel = dataModel();
+ ObjectPtr aObj = aModel->object(theIndex);
+ if (aObj.get()) {
+ ResultPtr aResObj = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ if (aResObj.get()) {
+ aResObj->setDisplayed(!aResObj->isDisplayed());
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ update(theIndex);
+ }
+ // Update list of selected objects because this event happens after
+ // selection event in object browser
+ XGUI_ObjectsBrowser* aObjBrowser = qobject_cast<XGUI_ObjectsBrowser*>(parent());
+ if (aObjBrowser) {
+ aObjBrowser->onSelectionChanged();
+ }
+ }
+}
+
+void XGUI_DataTree::onDoubleClick(const QModelIndex& theIndex)
+{
+ switch (theIndex.column()) {
+ case 2:
+ processHistoryChange(theIndex);
+ break;
}
}
//********************************************************************
//********************************************************************
//********************************************************************
-XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent)
- : QWidget(theParent), myDocModel(0)
+XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent, XGUI_Workshop* theWorkshop)
+ : QWidget(theParent), myDocModel(0), myWorkshop(theWorkshop)
{
QVBoxLayout* aLayout = new QVBoxLayout(this);
ModuleBase_Tools::zeroMargins(aLayout);
myTreeView->clear();
}
+//***************************************************
void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
const QItemSelection& theDeselected)
+{
+ onSelectionChanged();
+}
+
+//***************************************************
+void XGUI_ObjectsBrowser::onSelectionChanged()
{
emit selectionChanged();
}
+//***************************************************
QObjectPtrList XGUI_ObjectsBrowser::selectedObjects(QModelIndexList* theIndexes) const
{
QObjectPtrList aList;
XGUI_DataModel* aModel = dataModel();
QModelIndexList::const_iterator aIt;
for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
- if ((*aIt).column() == 0) {
+ if ((*aIt).column() == 1) {
ObjectPtr aObject = aModel->object(*aIt);
if (aObject) {
aList.append(aObject);
QModelIndex aRootIdx = aModel->documentRootIndex(theDoc);
int aNbChild = aModel->rowCount(aRootIdx);
for (int i = 0; i < aNbChild; i++) {
- QModelIndex aIdx = aModel->index(i, 0, aRootIdx);
+ QModelIndex aIdx = aModel->index(i, 1, aRootIdx);
aStates.push_back(myTreeView->isExpanded(aIdx));
}
return aStates;
class ModuleBase_IDocumentDataModel;
class XGUI_DataModel;
class Config_DataModelReader;
+class XGUI_Workshop;
+
+//#define DEBUG_INDXES
/**
* \ingroup GUI
/// Redefinition of virtual method
virtual void resizeEvent(QResizeEvent* theEvent);
+
+ /// Redefinition of virtual method
+ virtual void mouseReleaseEvent(QMouseEvent* theEvent);
+
+#ifdef DEBUG_INDXES
+ virtual void mousePressEvent(QMouseEvent* theEvent);
+#endif
+
+private:
+ /// Process a history change request
+ /// \param theIndex a clicked data index
+ void processHistoryChange(const QModelIndex& theIndex);
+
+ /// Process a visibility change request
+ /// \param theIndex a clicked data index
+ void processEyeClick(const QModelIndex& theIndex);
};
/**\class XGUI_ObjectsBrowser
public:
/// Constructor
/// \param theParent a parent widget
- XGUI_ObjectsBrowser(QWidget* theParent);
+ XGUI_ObjectsBrowser(QWidget* theParent, XGUI_Workshop* theWorkshop);
virtual ~XGUI_ObjectsBrowser();
//! Returns Model which provides access to data objects
/// \param theStates list of booleans with state expanded or not
void setStateForDoc(DocumentPtr theDoc, const std::list<bool>& theStates);
+ /// Returns current workshop
+ XGUI_Workshop* workshop() const { return myWorkshop; }
+
+ void onSelectionChanged();
+
+
public slots:
//! Called on Edit command request
void onEditItem();
XGUI_DataModel* myDocModel;
XGUI_ActiveDocLbl* myActiveDocLbl;
XGUI_DataTree* myTreeView;
+ XGUI_Workshop* myWorkshop;
/// A field to store expanded items before model reset
QModelIndexList myExpandedItems;
aObjDock->setWindowTitle(tr("Object browser"));
aObjDock->setStyleSheet(
"::title { position: relative; padding-left: 5px; text-align: left center }");
- myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
+ myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock, this);
myObjectBrowser->setXMLReader(myDataModelXMLReader);
myModule->customizeObjectBrowser(myObjectBrowser);
aObjDock->setWidget(myObjectBrowser);
#endif
aParameters.Append(MyVCallBack);
+ MyTCommunicator->RegisterPlugin("TKDFBrowser");
+ MyTCommunicator->RegisterPlugin("TKShapeView");
+ MyTCommunicator->RegisterPlugin("TKVInspector");
MyTCommunicator->RegisterPlugin("SMBrowser"); // custom plugin to view ModelAPI
MyTCommunicator->Init(aParameters);
<file>pictures/wire.png</file>
<file>pictures/result.png</file>
<file>pictures/find_result.png</file>
+
+ <file>pictures/eyeclosed.png</file>
+ <file>pictures/eyemiclosed.png</file>
+ <file>pictures/eyeopen.png</file>
</qresource>
</RCC>