]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_SketchDrawer.cpp
Salome HOME
First implementation of the sketch drawer: helper for creation of sketch on imported...
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_SketchDrawer.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "SketchPlugin_SketchDrawer.h"
22
23 #include "SketchPlugin_Arc.h"
24 #include "SketchPlugin_Line.h"
25 #include "SketchPlugin_Circle.h"
26 #include "SketchPlugin_Point.h"
27 #include "SketchPlugin_Sketch.h"
28 #include "SketchPlugin_ConstraintDistance.h"
29 #include "SketchPlugin_ConstraintCoincidence.h"
30 #include "SketchPlugin_ConstraintLength.h"
31 #include "SketchPlugin_ConstraintRadius.h"
32 #include "SketchPlugin_ConstraintVertical.h"
33 #include "SketchPlugin_ConstraintHorizontal.h"
34 #include "SketchPlugin_ConstraintDistanceVertical.h"
35 #include "SketchPlugin_ConstraintDistanceHorizontal.h"
36 #include "SketchPlugin_Tools.h"
37
38 #include <GeomAPI_Face.h>
39 #include <GeomAPI_Edge.h>
40 #include <GeomAPI_Circ.h>
41 #include <GeomAPI_ShapeExplorer.h>
42 #include <GeomAPI_DataMapOfShapeShape.h>
43
44 #include <ModelAPI_AttributeSelection.h>
45 #include <ModelAPI_AttributeDouble.h>
46 #include <ModelAPI_ResultConstruction.h>
47
48 static const double kTOL = 1.e-6;
49
50 SketchPlugin_SketchDrawer::SketchPlugin_SketchDrawer() : ModelAPI_Feature()
51 {}
52
53 void SketchPlugin_SketchDrawer::initAttributes()
54 {
55   data()->addAttribute(BASE_ID(), ModelAPI_AttributeSelection::typeId());
56   data()->addAttribute(PLANE_ID(), ModelAPI_AttributeSelection::typeId());
57 }
58
59 // sets a point attribute of the feature by 3D point on the sketch
60 static void setPoint(FeaturePtr theFeature, const std::string& theAttrID,
61   std::shared_ptr<SketchPlugin_Sketch> theSketch, GeomPointPtr thePoint,
62   std::list<std::pair<GeomPnt2dPtr, std::string> >& aPoints)
63 {
64   GeomPnt2dPtr aPnt2D = theSketch->to2D(thePoint);
65   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
66     theFeature->attribute(theAttrID))->setValue(aPnt2D);
67   aPoints.push_back(std::pair<GeomPnt2dPtr, std::string>(aPnt2D, theAttrID));
68 }
69
70 void SketchPlugin_SketchDrawer::execute()
71 {
72   GeomShapePtr aBase = selection(BASE_ID())->value();
73   if (!aBase.get() && selection(BASE_ID())->context().get())
74     aBase = selection(BASE_ID())->context()->shape();
75   if (!aBase.get()) {
76     setError("Error: a base shape can not be obtained");
77     return; // invalid case
78   }
79
80   ObjectPtr aPlaneContext = selection(PLANE_ID())->contextObject();
81   GeomShapePtr aPlaneShape = selection(PLANE_ID())->value();
82   if (!aPlaneShape.get() || aPlaneShape->shapeType() != GeomAPI_Shape::FACE) {
83     setError("Error: a sketch plane can not be obtained");
84     return; // invalid case
85   }
86   GeomFacePtr aPlaneFace(new GeomAPI_Face(aPlaneShape));
87   GeomPlanePtr aPlane = aPlaneFace->getPlane();
88
89   // create and initialize sketch
90   DocumentPtr aMyDoc = document();
91   std::shared_ptr<SketchPlugin_Sketch> aSketch =
92     std::dynamic_pointer_cast<SketchPlugin_Sketch>(aMyDoc->addFeature(SketchPlugin_Sketch::ID()));
93   /*if (aPlaneContext->groupName() == ModelAPI_ResultConstruction::group()) { // by coordinates
94     std::dynamic_pointer_cast<GeomDataAPI_Point>(
95       aSketch->attribute(SketchPlugin_Sketch::ORIGIN_ID()))->setValue(aPlane->location());
96     std::dynamic_pointer_cast<GeomDataAPI_Dir>(
97       aSketch->attribute(SketchPlugin_Sketch::NORM_ID()))->setValue(aPlane->direction());
98
99   } else {*/
100   // by selection of plane
101   aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
102     setValue(selection(PLANE_ID())->context(), aPlaneShape);
103   // if reference to non-construction, remove reference, but keep the sketch position
104   if (aPlaneContext->groupName() != ModelAPI_ResultConstruction::group()) {
105     aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
106       setValue(ResultPtr(), GeomShapePtr());
107   }
108
109   // iterate all edges of the base to find all edges that belong to this plane
110   GeomAPI_DataMapOfShapeShape alreadyProcessed;
111   std::list<AttributePoint2DPtr> aCreatedPoints;// points to check and set coincidence
112   for(GeomAPI_ShapeExplorer anEdges(aBase, GeomAPI_Shape::EDGE); anEdges.more(); anEdges.next()) {
113     if (!alreadyProcessed.bind(anEdges.current(), anEdges.current()))
114       continue; // skip duplicated edges
115     GeomEdgePtr anEdge(new GeomAPI_Edge(anEdges.current()));
116     if (anEdge->isDegenerated())
117       continue; // skip degenerated edges
118     GeomPointPtr aStart = anEdge->firstPoint();
119     GeomPointPtr anEnd = anEdge->lastPoint();
120     if (aPlane->distance(aStart) >= kTOL || aPlane->distance(anEnd) >= kTOL)
121       continue; // skip edges not in plane
122
123     FeaturePtr anItem;
124     std::list<std::pair<GeomPnt2dPtr, std::string> > aPoints; // created point to attribute ID
125     if (anEdge->isLine()) { // line is already in the plane: create by two points
126       anItem = aSketch->addFeature(SketchPlugin_Line::ID());
127       setPoint(anItem, SketchPlugin_Line::START_ID(), aSketch, aStart, aPoints);
128       setPoint(anItem, SketchPlugin_Line::END_ID(), aSketch, anEnd, aPoints);
129       anItem->execute(); // for constraints setting on result
130       // add a vertical or horizontal constraints
131       bool isHorVertConstr = true;
132       if (abs(aPoints.front().first->x() - aPoints.back().first->x()) < kTOL) {
133         FeaturePtr aVert = aSketch->addFeature(SketchPlugin_ConstraintVertical::ID());
134         aVert->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
135       } else if (abs(aPoints.front().first->y() - aPoints.back().first->y()) < kTOL) {
136         FeaturePtr aHor = aSketch->addFeature(SketchPlugin_ConstraintHorizontal::ID());
137         aHor->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
138       } else {
139         isHorVertConstr = false;
140       }
141       if (isHorVertConstr) { // only length constraint is enough
142         FeaturePtr aLen = aSketch->addFeature(SketchPlugin_ConstraintLength::ID());
143         aLen->refattr(SketchPlugin_ConstraintLength::ENTITY_A())->setObject(anItem->firstResult());
144         aLen->real(SketchPlugin_ConstraintLength::VALUE())->setValue(anEdge->length());
145       } else { // set horizontal and vertical distance constraints
146         FeaturePtr aVDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
147         aVDist->refattr(SketchPlugin_Constraint::ENTITY_A())
148           ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
149         aVDist->refattr(SketchPlugin_Constraint::ENTITY_B())
150           ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
151         aVDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
152           ->setValue(aPoints.back().first->y() - aPoints.front().first->y());
153         FeaturePtr aHDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
154         aHDist->refattr(SketchPlugin_Constraint::ENTITY_A())
155           ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
156         aHDist->refattr(SketchPlugin_Constraint::ENTITY_B())
157           ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
158         aHDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
159           ->setValue(aPoints.back().first->x() - aPoints.front().first->x());
160       }
161     } else if (anEdge->isArc()) { // check also center
162       GeomPointPtr aCenter = anEdge->circle()->center();
163       if (aPlane->distance(aCenter) >= kTOL)
164         continue;
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
172       FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
173       aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
174     } else if (anEdge->isCircle()) { // check also center and middle (at value 2.)
175       GeomPointPtr aCenter = anEdge->circle()->center();
176       if (aPlane->distance(aCenter) >= kTOL || aPlane->distance(anEdge->middlePoint()) >= kTOL)
177         continue;
178       // circle by center and radius
179       anItem = aSketch->addFeature(SketchPlugin_Circle::ID());
180       setPoint(anItem, SketchPlugin_Circle::CENTER_ID(), aSketch, aCenter, aPoints);
181       anItem->real(SketchPlugin_Circle::RADIUS_ID())->setValue(anEdge->circle()->radius());
182       anItem->execute(); // for constraints setting on result
183       // set radius constraint
184       FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
185       aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
186     } else {
187       continue; // other types of edges are not supported, only lines, circles and arcs
188     }
189     // check some resulting points are coincident to existing
190     std::list<std::pair<GeomPnt2dPtr, std::string> >::iterator aPIter = aPoints.begin();
191     for(; aPIter != aPoints.end(); aPIter++) {
192       AttributePoint2DPtr aPointAttr =
193         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anItem->attribute(aPIter->second));
194       std::list<AttributePoint2DPtr>::iterator aCoincIter = aCreatedPoints.begin();
195       for(; aCoincIter != aCreatedPoints.end(); aCoincIter++) {
196         double aDX = (*aCoincIter)->x() - aPIter->first->x();
197         if (abs(aDX) >= kTOL)
198           continue;
199         double aDY = (*aCoincIter)->y() - aPIter->first->y();
200         if (abs(aDY) >= kTOL)
201           continue;
202         // create a coincidence constraint
203         FeaturePtr aCoinc = aSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
204         aCoinc->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(aPointAttr);
205         aCoinc->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(*aCoincIter);
206         break; // only one coincidence per point
207       }
208       aCreatedPoints.push_back(aPointAttr);
209     }
210   }
211   aMyDoc->setCurrentFeature(aSketch, false);
212 }