1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "ModelGeomAlgo_Point2D.h"
23 #include <ModelAPI_Feature.h>
24 #include <ModelAPI_Result.h>
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_CompositeFeature.h>
27 #include <ModelAPI_Tools.h>
29 #include <ModelGeomAlgo_Shape.h>
31 #include <GeomAPI_ShapeIterator.h>
33 #include <GeomAlgoAPI_ShapeTools.h>
34 #include <GeomDataAPI_Point2D.h>
36 #include <GeomAPI_Pnt.h>
37 #include <GeomAPI_Pnt2d.h>
38 #include <GeomAPI_Vertex.h>
39 #include <GeomAPI_Dir.h>
40 #include <GeomAPI_Edge.h>
41 #include <GeomAPI_Lin.h>
42 #include <GeomAPI_Circ.h>
43 #include <GeomAPI_ShapeExplorer.h>
45 //#define DEBUG_POINT_INSIDE_SHAPE
46 #ifdef DEBUG_POINT_INSIDE_SHAPE
51 #pragma warning(disable : 4996) // for sprintf
54 std::shared_ptr<GeomDataAPI_Point2D> ModelGeomAlgo_Point2D::getPointOfRefAttr(
55 ModelAPI_Feature* theFeature,
56 const std::string& theAttribute,
57 const std::string& theObjectFeatureKind,
58 const std::string& theObjectFeatureAttribute)
60 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
62 /// essential check as it is called in openGl thread
63 if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
64 return std::shared_ptr<GeomDataAPI_Point2D>();
67 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
68 ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
69 if(anAttr.get() && anAttr->isInitialized()) {
70 aFeature = ModelAPI_Feature::feature(anAttr->object());
72 bool aFeatureOfObjectKind = !theObjectFeatureKind.empty() &&
73 !theObjectFeatureAttribute.empty() &&
74 aFeature->getKind() == theObjectFeatureKind;
75 if(aFeatureOfObjectKind)
76 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
77 aFeature->data()->attribute(theObjectFeatureAttribute));
78 else if (anAttr->attr())
79 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
85 void ModelGeomAlgo_Point2D::getPointsOfReference(
86 const std::shared_ptr<ModelAPI_Object>& theObject,
87 const std::string& theReferenceFeatureKind,
88 std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
89 const std::string& theObjectFeatureKind,
90 const std::string& theObjectFeatureAttribute,
91 const bool isSkipFeatureAttributes)
94 FeaturePtr aSourceFeature = ModelAPI_Feature::feature(theObject);
96 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
97 std::set<AttributePtr>::const_iterator aIt;
98 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
99 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
100 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
101 if (aRefFeature->getKind() == theReferenceFeatureKind) {
102 std::list<AttributePtr> anAttributes =
103 aRefFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
104 std::list<AttributePtr>::iterator anIter = anAttributes.begin(), aLast = anAttributes.end();
105 bool isSkippedAttribute = false;
106 if (isSkipFeatureAttributes) {
107 for(anIter = anAttributes.begin(); anIter != aLast && !isSkippedAttribute; anIter++) {
108 AttributeRefAttrPtr aRefAttribute =
109 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
110 if (aRefAttribute.get() && !aRefAttribute->isObject()) {
111 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
112 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttribute->attr());
113 FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aPointAttr->owner());
114 isSkippedAttribute = aSourceFeature == anAttributeFeature;
118 if (isSkippedAttribute)
121 // it searches the first point of AttributeRefAtt
122 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
123 for(anIter = anAttributes.begin(); anIter != aLast && !aPointAttr.get(); anIter++) {
124 AttributeRefAttrPtr aRefAttribute =
125 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
126 if (aRefAttribute.get()) {
127 aPointAttr = getPointOfRefAttr(aRefFeature.get(), aRefAttribute->id(),
128 theObjectFeatureKind, theObjectFeatureAttribute);
131 if (aPointAttr.get()) {
132 theAttributes.insert(aPointAttr);
137 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
138 if (aFeature.get()) {
139 const std::list<std::shared_ptr<ModelAPI_Result> > aResults = aFeature->results();
140 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
141 for (; aRIter != aResults.cend(); aRIter++) {
142 ResultPtr aResult = *aRIter;
143 getPointsOfReference(aResult, theReferenceFeatureKind, theAttributes, theObjectFeatureKind,
144 theObjectFeatureAttribute);
149 void appendPoint(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
150 const std::shared_ptr<ModelAPI_Result>& theResult,
151 ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
153 bool aPointFound = false;
154 FeaturePtr aPointFeature = ModelAPI_Feature::feature(theResult);
155 // check if the given point is already in the container in attribute list
156 for (ModelGeomAlgo_Point2D::PointToRefsMap::const_iterator
157 anIt = thePointToAttributeOrObject.begin();
158 anIt != thePointToAttributeOrObject.end() && !aPointFound; anIt++) {
159 std::shared_ptr<GeomAPI_Pnt> aPoint = anIt->first;
160 if (aPoint->isEqual(thePoint)) {
161 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes = anIt->second.first;
162 for (std::list<AttributePoint2DPtr>::const_iterator anAttrIt = anAttributes.begin();
163 anAttrIt != anAttributes.end() && !aPointFound; anAttrIt++) {
164 AttributePtr anAttribute = *anAttrIt;
165 aPointFound = ModelAPI_Feature::feature(anAttribute->owner()) == aPointFeature;
171 if (thePointToAttributeOrObject.find(thePoint) != thePointToAttributeOrObject.end())
172 thePointToAttributeOrObject.at(thePoint).second.push_back(theResult);
174 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
175 std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
176 anObjects.push_back(theResult);
177 thePointToAttributeOrObject[thePoint] = std::make_pair(anAttributes, anObjects);
179 #ifdef DEBUG_POINT_INSIDE_SHAPE
180 std::cout << "["<< thePoint->x() << ", " << thePoint->y() << "," << thePoint->z() << "]";
185 void appendShapePoints(const GeomShapePtr& theShape,
186 const std::shared_ptr<ModelAPI_Result>& theResult,
187 ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
192 switch (theShape->shapeType()) {
193 case GeomAPI_Shape::VERTEX: {
194 std::shared_ptr<GeomAPI_Vertex> aVertex =
195 std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(theShape));
196 std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
197 appendPoint(aPnt, theResult, thePointToAttributeOrObject);
200 case GeomAPI_Shape::EDGE: {
201 std::shared_ptr<GeomAPI_Edge> anEdge =
202 std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(theShape));
203 appendPoint(anEdge->firstPoint(), theResult, thePointToAttributeOrObject);
204 appendPoint(anEdge->lastPoint(), theResult, thePointToAttributeOrObject);
207 case GeomAPI_Shape::COMPOUND: {
208 for(GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
209 appendShapePoints(anIt.current(), theResult, thePointToAttributeOrObject);
217 void ModelGeomAlgo_Point2D::getPointsIntersectedShape(
218 const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
219 const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
220 PointToRefsMap& thePointToAttributeOrObject)
222 #ifdef DEBUG_POINT_INSIDE_SHAPE
223 std::cout << "ModelGeomAlgo_Point2D::getPointsIntersectedShape" << std::endl;
225 GeomShapePtr aFeatureShape;
227 std::set<ResultPtr> anEdgeShapes;
228 ModelGeomAlgo_Shape::shapesOfType(theBaseFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
229 if (anEdgeShapes.empty())
231 aFeatureShape = (*anEdgeShapes.begin())->shape();
234 std::list<std::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = theFeatures.begin(),
235 aLast = theFeatures.end();
236 for (; anIt != aLast; anIt++) {
237 FeaturePtr aFeature = *anIt;
238 if (aFeature.get() == theBaseFeature.get())
240 if (aFeature.get()) {
241 std::set<ResultPtr> anEdgeShapes;
242 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
243 if (anEdgeShapes.empty())
244 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::VERTEX, anEdgeShapes);
246 if (anEdgeShapes.empty())
248 ResultPtr aResult = *anEdgeShapes.begin();
249 GeomShapePtr aShape = aResult->shape();
251 GeomShapePtr aShapeOfIntersection = aFeatureShape->intersect(aShape);
252 #ifdef DEBUG_POINT_INSIDE_SHAPE
253 int aPrevSize = thePointToAttributeOrObject.size();
255 appendShapePoints(aShapeOfIntersection, aResult, thePointToAttributeOrObject);
256 #ifdef DEBUG_POINT_INSIDE_SHAPE
257 if (aPrevSize != thePointToAttributeOrObject.size())
258 std::cout << " <- appendShapePoints"
259 << thePointToAttributeOrObject.size() - aPrevSize << std::endl;
265 std::list<std::shared_ptr<GeomAPI_Pnt> > ModelGeomAlgo_Point2D::getSetOfPntIntersectedShape(
266 const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
267 const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
269 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
271 PointToRefsMap aRefsMap;
272 getPointsIntersectedShape(theBaseFeature, theFeatures, aRefsMap);
274 for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
275 aPointIt != aRefsMap.end(); aPointIt++)
276 aPoints.push_back(aPointIt->first);
281 void ModelGeomAlgo_Point2D::getPointsInsideShape(
282 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
283 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
284 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
285 const std::shared_ptr<GeomAPI_Dir>& theDirX,
286 const std::shared_ptr<GeomAPI_Dir>& theDirY,
287 PointToRefsMap& thePointToAttributeOrObject)
289 #ifdef DEBUG_POINT_INSIDE_SHAPE
290 std::cout << "ModelGeomAlgo_Point2D::getPointsInsideShape:" << std::endl;
292 std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
293 aLast = theAttributes.end();
294 for (; anIt != aLast; anIt++) {
295 std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
296 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
297 std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
298 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
299 if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
300 if (thePointToAttributeOrObject.find(aProjectedPoint) != thePointToAttributeOrObject.end())
301 thePointToAttributeOrObject.at(aProjectedPoint).first.push_back(anAttribute);
303 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
304 std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
305 anAttributes.push_back(anAttribute);
306 thePointToAttributeOrObject[aProjectedPoint] = std::make_pair(anAttributes, anObjects);
308 #ifdef DEBUG_POINT_INSIDE_SHAPE
309 std::cout << " " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
310 << "[" << aPoint->x() << ", " << aPoint->y() << ", " << aPoint->z() << "]"
315 #ifdef DEBUG_POINT_INSIDE_SHAPE
316 std::cout << " " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
317 << "OUT of shape" << std::endl;
323 void ModelGeomAlgo_Point2D::getPointsInsideShape_p(
324 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
325 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
326 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
327 const std::shared_ptr<GeomAPI_Dir>& theDirX,
328 const std::shared_ptr<GeomAPI_Dir>& theDirY,
329 std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
330 std::map<std::shared_ptr<GeomDataAPI_Point2D>,
331 std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint)
333 std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
334 aLast = theAttributes.end();
335 for (; anIt != aLast; anIt++) {
336 std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
337 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
338 std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
339 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
340 if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
341 thePoints.push_back(aProjectedPoint);
342 theAttributeToPoint[anAttribute] = aProjectedPoint;
347 bool ModelGeomAlgo_Point2D::isPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
348 const std::shared_ptr<GeomAPI_Pnt>& thePoint,
349 std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
351 bool isInside = false;
352 if (theBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
353 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
354 if (anEdge->isLine()) {
355 std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
356 theProjectedPoint = aLine->project(thePoint);
358 else if (anEdge->isCircle() || anEdge->isArc()) {
359 std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
360 theProjectedPoint = aCircle->project(thePoint);
362 if (theProjectedPoint.get()) {
363 std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(theProjectedPoint->x(),
364 theProjectedPoint->y(), theProjectedPoint->z()));
365 isInside = GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, theBaseShape);
372 bool ModelGeomAlgo_Point2D::isInnerPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
373 const std::shared_ptr<GeomAPI_Pnt>& thePoint,
374 std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
376 bool isInside = isPointOnEdge(theBaseShape, thePoint, theProjectedPoint);
378 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
379 if (!anEdge->isCircle()) {
380 // check the point is not on the boundary
381 GeomVertexPtr aVertex(new GeomAPI_Vertex(theProjectedPoint->x(),
382 theProjectedPoint->y(), theProjectedPoint->z()));
383 GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX);
384 for (; anExp.more(); anExp.next()) {
385 GeomVertexPtr aCurV = anExp.current()->vertex();
386 isInside = !GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertex, aCurV);
393 std::string doubleToString(double theValue)
395 std::string aValueStr;
397 int n = sprintf(aBuf, "%g", theValue);
398 aValueStr = std::string(aBuf);
403 std::string ModelGeomAlgo_Point2D::getPontAttributesInfo(
404 const std::shared_ptr<ModelAPI_Feature>& theFeature,
405 const std::set<std::shared_ptr<ModelAPI_Attribute> >& theAttributesOnly)
409 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
410 GeomDataAPI_Point2D::typeId());
411 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
413 for(; anIt != aLast; anIt++) {
414 AttributePtr anAttribute = *anIt;
415 if (anAttribute.get() && (theAttributesOnly.empty() ||
416 theAttributesOnly.find(anAttribute) != theAttributesOnly.end())) {
417 if (!anInfo.empty()) {
421 anInfo.append(" " + getPointAttributeInfo(anAttribute));
427 std::string ModelGeomAlgo_Point2D::getPointAttributeInfo(
428 const std::shared_ptr<ModelAPI_Attribute>& theAttribute)
431 std::string aValue = "not defined";
432 std::string aType = theAttribute->attributeType();
433 if (aType == GeomDataAPI_Point2D::typeId()) {
434 std::shared_ptr<GeomDataAPI_Point2D> aPoint =
435 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
436 if (aPoint.get() && aPoint->isInitialized()) {
437 aValue = std::string("(" + doubleToString(aPoint->x()) + ", "+
438 doubleToString(aPoint->y()) + ")");
441 anInfo.append(theAttribute->id() + ": " + aValue);