1 // Copyright (C) 2014-2023 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SketchPlugin_SketchDrawer.h"
22 #include "SketchPlugin_Arc.h"
23 #include "SketchPlugin_Line.h"
24 #include "SketchPlugin_Circle.h"
25 #include "SketchPlugin_Point.h"
26 #include "SketchPlugin_Sketch.h"
27 #include "SketchPlugin_ConstraintDistance.h"
28 #include "SketchPlugin_ConstraintCoincidence.h"
29 #include "SketchPlugin_ConstraintLength.h"
30 #include "SketchPlugin_ConstraintRadius.h"
31 #include "SketchPlugin_ConstraintVertical.h"
32 #include "SketchPlugin_ConstraintHorizontal.h"
33 #include "SketchPlugin_ConstraintDistanceVertical.h"
34 #include "SketchPlugin_ConstraintDistanceHorizontal.h"
35 #include "SketchPlugin_Tools.h"
37 #include <GeomAPI_Face.h>
38 #include <GeomAPI_Edge.h>
39 #include <GeomAPI_Circ.h>
40 #include <GeomAPI_ShapeExplorer.h>
41 #include <GeomAPI_DataMapOfShapeShape.h>
43 #include <ModelAPI_AttributeSelection.h>
44 #include <ModelAPI_AttributeDouble.h>
45 #include <ModelAPI_AttributeBoolean.h>
46 #include <ModelAPI_ResultConstruction.h>
50 static const double kTOL = 1.e-6;
52 SketchPlugin_SketchDrawer::SketchPlugin_SketchDrawer() : ModelAPI_Feature()
55 void SketchPlugin_SketchDrawer::initAttributes()
57 data()->addAttribute(BASE_ID(), ModelAPI_AttributeSelection::typeId());
58 data()->addAttribute(PLANE_ID(), ModelAPI_AttributeSelection::typeId());
59 data()->addAttribute(ADD_DIMENSIONS_ID(), ModelAPI_AttributeBoolean::typeId());
62 // sets a point attribute of the feature by 3D point on the sketch
63 static void setPoint(FeaturePtr theFeature, const std::string& theAttrID,
64 std::shared_ptr<SketchPlugin_Sketch> theSketch, GeomPointPtr thePoint,
65 std::list<std::pair<GeomPnt2dPtr, std::string> >& aPoints)
67 GeomPnt2dPtr aPnt2D = theSketch->to2D(thePoint);
68 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
69 theFeature->attribute(theAttrID))->setValue(aPnt2D);
70 aPoints.push_back(std::pair<GeomPnt2dPtr, std::string>(aPnt2D, theAttrID));
73 void SketchPlugin_SketchDrawer::execute()
75 GeomShapePtr aBase = selection(BASE_ID())->value();
76 if (!aBase.get() && selection(BASE_ID())->context().get())
77 aBase = selection(BASE_ID())->context()->shape();
79 setError("Error: a base shape can not be obtained");
80 return; // invalid case
83 ObjectPtr aPlaneContext = selection(PLANE_ID())->contextObject();
84 GeomShapePtr aPlaneShape = selection(PLANE_ID())->value();
85 if (!aPlaneShape.get() && aPlaneContext.get())
86 aPlaneShape = selection(PLANE_ID())->context()->shape();
87 if (!aPlaneShape.get() || aPlaneShape->shapeType() != GeomAPI_Shape::FACE) {
88 setError("Error: a sketch plane can not be obtained");
89 return; // invalid case
91 GeomFacePtr aPlaneFace(new GeomAPI_Face(aPlaneShape));
92 GeomPlanePtr aPlane = aPlaneFace->getPlane();
94 // create and initialize sketch
95 DocumentPtr aMyDoc = document();
96 std::shared_ptr<SketchPlugin_Sketch> aSketch =
97 std::dynamic_pointer_cast<SketchPlugin_Sketch>(aMyDoc->addFeature(SketchPlugin_Sketch::ID()));
98 // by selection of plane
99 aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
100 setValue(selection(PLANE_ID())->context(), aPlaneShape);
101 // remove reference, but keep the sketch position
102 aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
103 setValue(ResultPtr(), GeomShapePtr());
105 bool addDimensions = boolean(ADD_DIMENSIONS_ID())->value();
106 // iterate all edges of the base to find all edges that belong to this plane
107 GeomAPI_DataMapOfShapeShape alreadyProcessed;
108 std::list<AttributePoint2DPtr> aCreatedPoints;// points to check and set coincidence
109 for(GeomAPI_ShapeExplorer anEdges(aBase, GeomAPI_Shape::EDGE); anEdges.more(); anEdges.next()) {
110 if (!alreadyProcessed.bind(anEdges.current(), anEdges.current()))
111 continue; // skip duplicated edges
112 GeomEdgePtr anEdge(new GeomAPI_Edge(anEdges.current()));
113 if (anEdge->isDegenerated())
114 continue; // skip degenerated edges
115 GeomPointPtr aStart = anEdge->firstPoint();
116 GeomPointPtr anEnd = anEdge->lastPoint();
117 if (aPlane->distance(aStart) >= kTOL || aPlane->distance(anEnd) >= kTOL)
118 continue; // skip edges not in plane
121 std::list<std::pair<GeomPnt2dPtr, std::string> > aPoints; // created point to attribute ID
122 if (anEdge->isLine()) { // line is already in the plane: create by two points
123 anItem = aSketch->addFeature(SketchPlugin_Line::ID());
124 setPoint(anItem, SketchPlugin_Line::START_ID(), aSketch, aStart, aPoints);
125 setPoint(anItem, SketchPlugin_Line::END_ID(), aSketch, anEnd, aPoints);
126 anItem->execute(); // for constraints setting on result
127 // add a vertical or horizontal constraints
128 bool isHorVertConstr = true;
129 if (fabs(aPoints.front().first->x() - aPoints.back().first->x()) < kTOL) {
130 FeaturePtr aVert = aSketch->addFeature(SketchPlugin_ConstraintVertical::ID());
131 aVert->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
132 } else if (fabs(aPoints.front().first->y() - aPoints.back().first->y()) < kTOL) {
133 FeaturePtr aHor = aSketch->addFeature(SketchPlugin_ConstraintHorizontal::ID());
134 aHor->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
136 isHorVertConstr = false;
139 if (isHorVertConstr) { // only length constraint is enough
140 FeaturePtr aLen = aSketch->addFeature(SketchPlugin_ConstraintLength::ID());
141 aLen->refattr(SketchPlugin_ConstraintLength::ENTITY_A())
142 ->setObject(anItem->firstResult());
143 aLen->real(SketchPlugin_ConstraintLength::VALUE())->setValue(anEdge->length());
144 } else { // set horizontal and vertical distance constraints
145 FeaturePtr aVDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
146 aVDist->refattr(SketchPlugin_Constraint::ENTITY_A())
147 ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
148 aVDist->refattr(SketchPlugin_Constraint::ENTITY_B())
149 ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
150 aVDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
151 ->setValue(aPoints.back().first->y() - aPoints.front().first->y());
152 FeaturePtr aHDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
153 aHDist->refattr(SketchPlugin_Constraint::ENTITY_A())
154 ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
155 aHDist->refattr(SketchPlugin_Constraint::ENTITY_B())
156 ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
157 aHDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
158 ->setValue(aPoints.back().first->x() - aPoints.front().first->x());
161 } else if (anEdge->isArc()) { // check also center
162 GeomPointPtr aCenter = anEdge->circle()->center();
163 if (aPlane->distance(aCenter) >= kTOL)
165 // create arc by 3 points
166 anItem = aSketch->addFeature(SketchPlugin_Arc::ID());
167 setPoint(anItem, SketchPlugin_Arc::CENTER_ID(), aSketch, aCenter, aPoints);
168 setPoint(anItem, SketchPlugin_Arc::START_ID(), aSketch, aStart, aPoints);
169 setPoint(anItem, SketchPlugin_Arc::END_ID(), aSketch, anEnd, aPoints);
170 anItem->execute(); // for constraints setting on result
171 // set radius constraint
173 FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
174 aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
176 } else if (anEdge->isCircle()) { // check also center and middle (at value 2.)
177 GeomPointPtr aCenter = anEdge->circle()->center();
178 if (aPlane->distance(aCenter) >= kTOL || aPlane->distance(anEdge->middlePoint()) >= kTOL)
180 // circle by center and radius
181 anItem = aSketch->addFeature(SketchPlugin_Circle::ID());
182 setPoint(anItem, SketchPlugin_Circle::CENTER_ID(), aSketch, aCenter, aPoints);
183 anItem->real(SketchPlugin_Circle::RADIUS_ID())->setValue(anEdge->circle()->radius());
184 anItem->execute(); // for constraints setting on result
185 // set radius constraint
187 FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
188 aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
191 continue; // other types of edges are not supported, only lines, circles and arcs
193 // check some resulting points are coincident to existing
194 std::list<std::pair<GeomPnt2dPtr, std::string> >::iterator aPIter = aPoints.begin();
195 for(; aPIter != aPoints.end(); aPIter++) {
196 AttributePoint2DPtr aPointAttr =
197 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anItem->attribute(aPIter->second));
198 std::list<AttributePoint2DPtr>::iterator aCoincIter = aCreatedPoints.begin();
199 for(; aCoincIter != aCreatedPoints.end(); aCoincIter++) {
200 double aDX = (*aCoincIter)->x() - aPIter->first->x();
201 if (fabs(aDX) >= kTOL)
203 double aDY = (*aCoincIter)->y() - aPIter->first->y();
204 if (fabs(aDY) >= kTOL)
206 // create a coincidence constraint
207 FeaturePtr aCoinc = aSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
208 aCoinc->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(aPointAttr);
209 aCoinc->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(*aCoincIter);
210 break; // only one coincidence per point
212 aCreatedPoints.push_back(aPointAttr);
215 aMyDoc->setCurrentFeature(aSketch, false);