1 // Copyright (C) 2014-2019 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 email : webmaster.salome@opencascade.com
20 #include "ModelGeomAlgo_Point2D.h"
22 #include <ModelAPI_Feature.h>
23 #include <ModelAPI_Result.h>
24 #include <ModelAPI_AttributeRefAttr.h>
25 #include <ModelAPI_CompositeFeature.h>
26 #include <ModelAPI_Tools.h>
28 #include <ModelGeomAlgo_Shape.h>
30 #include <GeomAPI_ShapeIterator.h>
32 #include <GeomAlgoAPI_ShapeTools.h>
33 #include <GeomDataAPI_Point2D.h>
35 #include <GeomAPI_Pnt.h>
36 #include <GeomAPI_Pnt2d.h>
37 #include <GeomAPI_Vertex.h>
38 #include <GeomAPI_Dir.h>
39 #include <GeomAPI_Edge.h>
40 #include <GeomAPI_Lin.h>
41 #include <GeomAPI_Circ.h>
42 #include <GeomAPI_ShapeExplorer.h>
44 //#define DEBUG_POINT_INSIDE_SHAPE
45 #ifdef DEBUG_POINT_INSIDE_SHAPE
50 #pragma warning(disable : 4996) // for sprintf
53 std::shared_ptr<GeomDataAPI_Point2D> ModelGeomAlgo_Point2D::getPointOfRefAttr(
54 ModelAPI_Feature* theFeature,
55 const std::string& theAttribute,
56 const std::string& theObjectFeatureKind,
57 const std::string& theObjectFeatureAttribute)
59 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
61 /// essential check as it is called in openGl thread
62 if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
63 return std::shared_ptr<GeomDataAPI_Point2D>();
66 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
67 ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
68 if(anAttr.get() && anAttr->isInitialized()) {
69 aFeature = ModelAPI_Feature::feature(anAttr->object());
71 bool aFeatureOfObjectKind = !theObjectFeatureKind.empty() &&
72 !theObjectFeatureAttribute.empty() &&
73 aFeature->getKind() == theObjectFeatureKind;
74 if(aFeatureOfObjectKind)
75 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
76 aFeature->data()->attribute(theObjectFeatureAttribute));
77 else if (anAttr->attr())
78 aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
84 void ModelGeomAlgo_Point2D::getPointsOfReference(
85 const std::shared_ptr<ModelAPI_Object>& theObject,
86 const std::string& theReferenceFeatureKind,
87 std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
88 const std::string& theObjectFeatureKind,
89 const std::string& theObjectFeatureAttribute,
90 const bool isSkipFeatureAttributes)
93 FeaturePtr aSourceFeature = ModelAPI_Feature::feature(theObject);
95 const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
96 std::set<AttributePtr>::const_iterator aIt;
97 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
98 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
99 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
100 if (aRefFeature->getKind() == theReferenceFeatureKind) {
101 std::list<AttributePtr> anAttributes =
102 aRefFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
103 std::list<AttributePtr>::iterator anIter = anAttributes.begin(), aLast = anAttributes.end();
104 bool isSkippedAttribute = false;
105 if (isSkipFeatureAttributes) {
106 for(anIter = anAttributes.begin(); anIter != aLast && !isSkippedAttribute; anIter++) {
107 AttributeRefAttrPtr aRefAttribute =
108 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
109 if (aRefAttribute.get() && !aRefAttribute->isObject()) {
110 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
111 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttribute->attr());
112 FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aPointAttr->owner());
113 isSkippedAttribute = aSourceFeature == anAttributeFeature;
117 if (isSkippedAttribute)
120 // it searches the first point of AttributeRefAtt
121 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
122 for(anIter = anAttributes.begin(); anIter != aLast && !aPointAttr.get(); anIter++) {
123 AttributeRefAttrPtr aRefAttribute =
124 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
125 if (aRefAttribute.get()) {
126 aPointAttr = getPointOfRefAttr(aRefFeature.get(), aRefAttribute->id(),
127 theObjectFeatureKind, theObjectFeatureAttribute);
130 if (aPointAttr.get()) {
131 theAttributes.insert(aPointAttr);
136 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
137 if (aFeature.get()) {
138 const std::list<std::shared_ptr<ModelAPI_Result> > aResults = aFeature->results();
139 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
140 for (; aRIter != aResults.cend(); aRIter++) {
141 ResultPtr aResult = *aRIter;
142 getPointsOfReference(aResult, theReferenceFeatureKind, theAttributes, theObjectFeatureKind,
143 theObjectFeatureAttribute);
148 void appendPoint(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
149 const std::shared_ptr<ModelAPI_Result>& theResult,
150 ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
152 bool aPointFound = false;
153 FeaturePtr aPointFeature = ModelAPI_Feature::feature(theResult);
154 // check if the given point is already in the container in attribute list
155 for (ModelGeomAlgo_Point2D::PointToRefsMap::const_iterator
156 anIt = thePointToAttributeOrObject.begin();
157 anIt != thePointToAttributeOrObject.end() && !aPointFound; anIt++) {
158 std::shared_ptr<GeomAPI_Pnt> aPoint = anIt->first;
159 if (aPoint->isEqual(thePoint)) {
160 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes = anIt->second.first;
161 for (std::list<AttributePoint2DPtr>::const_iterator anAttrIt = anAttributes.begin();
162 anAttrIt != anAttributes.end() && !aPointFound; anAttrIt++) {
163 AttributePtr anAttribute = *anAttrIt;
164 aPointFound = ModelAPI_Feature::feature(anAttribute->owner()) == aPointFeature;
170 if (thePointToAttributeOrObject.find(thePoint) != thePointToAttributeOrObject.end())
171 thePointToAttributeOrObject.at(thePoint).second.push_back(theResult);
173 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
174 std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
175 anObjects.push_back(theResult);
176 thePointToAttributeOrObject[thePoint] = std::make_pair(anAttributes, anObjects);
178 #ifdef DEBUG_POINT_INSIDE_SHAPE
179 std::cout << "["<< thePoint->x() << ", " << thePoint->y() << "," << thePoint->z() << "]";
184 void appendShapePoints(const GeomShapePtr& theShape,
185 const std::shared_ptr<ModelAPI_Result>& theResult,
186 ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
191 switch (theShape->shapeType()) {
192 case GeomAPI_Shape::VERTEX: {
193 std::shared_ptr<GeomAPI_Vertex> aVertex =
194 std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(theShape));
195 std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
196 appendPoint(aPnt, theResult, thePointToAttributeOrObject);
199 case GeomAPI_Shape::EDGE: {
200 std::shared_ptr<GeomAPI_Edge> anEdge =
201 std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(theShape));
202 appendPoint(anEdge->firstPoint(), theResult, thePointToAttributeOrObject);
203 appendPoint(anEdge->lastPoint(), theResult, thePointToAttributeOrObject);
206 case GeomAPI_Shape::COMPOUND: {
207 for(GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
208 appendShapePoints(anIt.current(), theResult, thePointToAttributeOrObject);
216 void ModelGeomAlgo_Point2D::getPointsIntersectedShape(
217 const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
218 const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
219 PointToRefsMap& thePointToAttributeOrObject)
221 #ifdef DEBUG_POINT_INSIDE_SHAPE
222 std::cout << "ModelGeomAlgo_Point2D::getPointsIntersectedShape" << std::endl;
224 GeomShapePtr aFeatureShape;
226 std::set<ResultPtr> anEdgeShapes;
227 ModelGeomAlgo_Shape::shapesOfType(theBaseFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
228 if (anEdgeShapes.empty())
230 aFeatureShape = (*anEdgeShapes.begin())->shape();
233 std::list<std::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = theFeatures.begin(),
234 aLast = theFeatures.end();
235 for (; anIt != aLast; anIt++) {
236 FeaturePtr aFeature = *anIt;
237 if (aFeature.get() == theBaseFeature.get())
239 if (aFeature.get()) {
240 std::set<ResultPtr> anEdgeShapes;
241 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
242 if (anEdgeShapes.empty())
243 ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::VERTEX, anEdgeShapes);
245 if (anEdgeShapes.empty())
247 ResultPtr aResult = *anEdgeShapes.begin();
248 GeomShapePtr aShape = aResult->shape();
250 GeomShapePtr aShapeOfIntersection = aFeatureShape->intersect(aShape);
251 #ifdef DEBUG_POINT_INSIDE_SHAPE
252 int aPrevSize = thePointToAttributeOrObject.size();
254 appendShapePoints(aShapeOfIntersection, aResult, thePointToAttributeOrObject);
255 #ifdef DEBUG_POINT_INSIDE_SHAPE
256 if (aPrevSize != thePointToAttributeOrObject.size())
257 std::cout << " <- appendShapePoints"
258 << thePointToAttributeOrObject.size() - aPrevSize << std::endl;
264 std::list<std::shared_ptr<GeomAPI_Pnt> > ModelGeomAlgo_Point2D::getSetOfPntIntersectedShape(
265 const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
266 const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
268 std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
270 PointToRefsMap aRefsMap;
271 getPointsIntersectedShape(theBaseFeature, theFeatures, aRefsMap);
273 for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
274 aPointIt != aRefsMap.end(); aPointIt++)
275 aPoints.push_back(aPointIt->first);
280 void ModelGeomAlgo_Point2D::getPointsInsideShape(
281 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
282 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
283 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
284 const std::shared_ptr<GeomAPI_Dir>& theDirX,
285 const std::shared_ptr<GeomAPI_Dir>& theDirY,
286 PointToRefsMap& thePointToAttributeOrObject)
288 #ifdef DEBUG_POINT_INSIDE_SHAPE
289 std::cout << "ModelGeomAlgo_Point2D::getPointsInsideShape:" << std::endl;
291 std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
292 aLast = theAttributes.end();
293 for (; anIt != aLast; anIt++) {
294 std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
295 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
296 std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
297 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
298 if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
299 if (thePointToAttributeOrObject.find(aProjectedPoint) != thePointToAttributeOrObject.end())
300 thePointToAttributeOrObject.at(aProjectedPoint).first.push_back(anAttribute);
302 std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
303 std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
304 anAttributes.push_back(anAttribute);
305 thePointToAttributeOrObject[aProjectedPoint] = std::make_pair(anAttributes, anObjects);
307 #ifdef DEBUG_POINT_INSIDE_SHAPE
308 std::cout << " " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
309 << "[" << aPoint->x() << ", " << aPoint->y() << ", " << aPoint->z() << "]"
314 #ifdef DEBUG_POINT_INSIDE_SHAPE
315 std::cout << " " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
316 << "OUT of shape" << std::endl;
322 void ModelGeomAlgo_Point2D::getPointsInsideShape_p(
323 const std::shared_ptr<GeomAPI_Shape> theBaseShape,
324 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
325 const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
326 const std::shared_ptr<GeomAPI_Dir>& theDirX,
327 const std::shared_ptr<GeomAPI_Dir>& theDirY,
328 std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
329 std::map<std::shared_ptr<GeomDataAPI_Point2D>,
330 std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint)
332 std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
333 aLast = theAttributes.end();
334 for (; anIt != aLast; anIt++) {
335 std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
336 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
337 std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
338 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
339 if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
340 thePoints.push_back(aProjectedPoint);
341 theAttributeToPoint[anAttribute] = aProjectedPoint;
346 bool ModelGeomAlgo_Point2D::isPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
347 const std::shared_ptr<GeomAPI_Pnt>& thePoint,
348 std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
350 bool isInside = false;
351 if (theBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
352 GeomCurvePtr aCurve(new GeomAPI_Curve(theBaseShape->edge()));
353 theProjectedPoint = aCurve->project(thePoint);
354 if (theProjectedPoint.get()) {
355 std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(theProjectedPoint->x(),
356 theProjectedPoint->y(), theProjectedPoint->z()));
357 isInside = GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, theBaseShape);
364 bool ModelGeomAlgo_Point2D::isInnerPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
365 const std::shared_ptr<GeomAPI_Pnt>& thePoint,
366 std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
368 bool isInside = isPointOnEdge(theBaseShape, thePoint, theProjectedPoint);
370 std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
371 if (!anEdge->isClosed()) {
372 // check the point is not on the boundary
373 GeomVertexPtr aVertex(new GeomAPI_Vertex(theProjectedPoint->x(),
374 theProjectedPoint->y(), theProjectedPoint->z()));
375 GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX);
376 for (; anExp.more(); anExp.next()) {
377 GeomVertexPtr aCurV = anExp.current()->vertex();
378 isInside = !GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertex, aCurV);
385 std::string doubleToString(double theValue)
387 std::string aValueStr;
389 int n = sprintf(aBuf, "%g", theValue);
390 aValueStr = std::string(aBuf);
395 std::string ModelGeomAlgo_Point2D::getPontAttributesInfo(
396 const std::shared_ptr<ModelAPI_Feature>& theFeature,
397 const std::set<std::shared_ptr<ModelAPI_Attribute> >& theAttributesOnly)
401 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
402 GeomDataAPI_Point2D::typeId());
403 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
405 for(; anIt != aLast; anIt++) {
406 AttributePtr anAttribute = *anIt;
407 if (anAttribute.get() && (theAttributesOnly.empty() ||
408 theAttributesOnly.find(anAttribute) != theAttributesOnly.end())) {
409 if (!anInfo.empty()) {
413 anInfo.append(" " + getPointAttributeInfo(anAttribute));
419 std::string ModelGeomAlgo_Point2D::getPointAttributeInfo(
420 const std::shared_ptr<ModelAPI_Attribute>& theAttribute)
423 std::string aValue = "not defined";
424 std::string aType = theAttribute->attributeType();
425 if (aType == GeomDataAPI_Point2D::typeId()) {
426 std::shared_ptr<GeomDataAPI_Point2D> aPoint =
427 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
428 if (aPoint.get() && aPoint->isInitialized()) {
429 aValue = std::string("(" + doubleToString(aPoint->x()) + ", "+
430 doubleToString(aPoint->y()) + ")");
433 anInfo.append(theAttribute->id() + ": " + aValue);