1 // Copyright (C) 2014-2022 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 "GeomAlgoAPI_ShapeInfo.h"
21 #include "GeomAlgoAPI_BoundingBox.h"
23 #include <GeomAPI_Circ.h>
24 #include <GeomAPI_Ellipse.h>
25 #include <GeomAPI_Wire.h>
26 #include <GeomAPI_Pln.h>
27 #include <GeomAPI_Sphere.h>
28 #include <GeomAPI_Cone.h>
29 #include <GeomAPI_Cylinder.h>
30 #include <GeomAPI_Torus.h>
31 #include <GeomAPI_Shell.h>
32 #include <GeomAPI_Box.h>
34 #include <Precision.hxx>
38 std::string GeomAlgoAPI_ShapeInfo::html(Translator* theTranslator)
40 Values aVal(TYPE_HTML);
42 aVal.setTranslator(theTranslator);
47 std::list<GeomAlgoAPI_InfoValue> GeomAlgoAPI_ShapeInfo::values()
49 Values aVal(TYPE_VALS);
54 void GeomAlgoAPI_ShapeInfo::processShape(GeomAlgoAPI_ShapeInfo::Values& theVals)
56 switch (myShape->shapeType()) {
57 case GeomAPI_Shape::VERTEX:
59 GeomPointPtr aPoint = myShape->vertex()->point();
60 setShapeType("Vertex");
61 theVals.addPoint("Coordinates", myShape->vertex()->point());
64 case GeomAPI_Shape::EDGE:
66 GeomEdgePtr anEdge = myShape->edge();
67 processEdge(theVals, anEdge);
70 case GeomAPI_Shape::FACE:
72 GeomFacePtr aFace = myShape->face();
73 processFace(theVals, aFace);
76 case GeomAPI_Shape::SOLID: // nearly same as SHELL if it is only one sub
78 ListOfShape aShells = myShape->subShapes(GeomAPI_Shape::SHELL);
79 if (aShells.size() == 1)
81 GeomShapePtr aTmpShape = myShape;
82 myShape = aShells.front();
83 processShape(theVals);
86 if (myShapeType.empty() || myShapeType == "Shell")
87 setShapeType("Solid");
90 case GeomAPI_Shape::SHELL:
92 GeomShellPtr aShell = myShape->shell();
93 if (GeomBoxPtr aBox = aShell->getParallelepiped())
95 if (aBox->isAxesAligned()) {
99 setShapeType("Rotated Box");
102 else { // check single face
103 ListOfShape aFaces = myShape->subShapes(GeomAPI_Shape::FACE);
104 if (aFaces.size() == 1)
106 GeomFacePtr aFace = aFaces.front()->face();
107 processFace(theVals, aFace);
109 if (myShapeType.empty() || myShapeType == "Face")
110 setShapeType("Shell");
114 case GeomAPI_Shape::WIRE:
116 theVals.addNamedValue("Closed", myShape->wire()->isClosed());
118 // check the wire is a polygon
119 std::list<GeomPointPtr> aPolygonPoints;
120 if (myShape->wire()->isPolygon(aPolygonPoints)) {
121 setShapeType("Polygon");
122 std::string aPointTr = theVals.translator()->translate("Point");
123 std::list<GeomPointPtr>::const_iterator aPtIt = aPolygonPoints.begin();
124 for (int aCornerIndex = 0; aPtIt != aPolygonPoints.end(); ++aPtIt) {
125 std::ostringstream aStr;
126 aStr << " " << (++aCornerIndex);
127 theVals.addPoint(aStr.str().c_str(), *aPtIt);
131 setShapeType("Wire");
134 case GeomAPI_Shape::COMPSOLID:
135 case GeomAPI_Shape::COMPOUND:
137 setShapeType(myShape->shapeType() == GeomAPI_Shape::COMPSOLID ? "CompSolid" : "Compound");
138 double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
139 if (myShape->computeSize(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax))
141 theVals.addGroupName("Bounding box");
142 GeomPointPtr aMinPoint(new GeomAPI_Pnt(aXmin, aYmin, aZmin));
143 theVals.addPoint("Minimal corner", aMinPoint);
144 GeomPointPtr aMaxPoint(new GeomAPI_Pnt(aXmax, aYmax, aZmax));
145 theVals.addPoint("Maximal corner", aMaxPoint);
149 default: // nothing to fill
154 void GeomAlgoAPI_ShapeInfo::processEdge(Values& theVals, GeomEdgePtr theEdge)
156 setShapeType("Edge"); // Common case
157 if (theEdge->isDegenerated()) {
158 theVals.addNamedValue("Degenerated", true);
162 GeomPointPtr aStartPnt = theEdge->firstPoint();
163 GeomPointPtr aEndPnt = theEdge->lastPoint();
164 bool addStartEndPoints = false;
166 if (theEdge->isLine()) {
167 setShapeType("Line segment");
168 addStartEndPoints = true;
170 else if (GeomCirclePtr aCircle = theEdge->circle()) {
171 addStartEndPoints = aStartPnt->distance(aEndPnt) >= Precision::Confusion();
172 setShapeType(addStartEndPoints ? "Arc of circle" : "Circle");
173 theVals.addPoint("Center", aCircle->center());
174 theVals.addDirection("Normal", aCircle->normal());
175 theVals.addGroupName("Dimensions");
176 theVals.addNamedValue("Radius", aCircle->radius());
178 else if (GeomEllipsePtr anEllipse = theEdge->ellipse()) {
179 addStartEndPoints = aStartPnt->distance(aEndPnt) >= Precision::Confusion();
180 setShapeType(addStartEndPoints ? "Arc of ellipse" : "Ellipse");
181 theVals.addPoint("Center", anEllipse->center());
182 theVals.addDirection("Normal", anEllipse->normal());
183 theVals.addGroupName("Dimensions");
184 theVals.addNamedValue("Major radius", anEllipse->majorRadius());
185 theVals.addNamedValue("Minor radius", anEllipse->minorRadius());
188 if (addStartEndPoints) {
189 theVals.addPoint("Start point", aStartPnt);
190 theVals.addPoint("End point", aEndPnt);
194 void GeomAlgoAPI_ShapeInfo::processFace(Values& theVals, GeomFacePtr theFace)
196 // Plane and planar face
197 if (GeomPlanePtr aPlane = theFace->getPlane()) {
198 bool isCommonCase = true;
199 // Check face bounded by circle or ellipse
200 std::list<GeomShapePtr> aSubs = theFace->subShapes(GeomAPI_Shape::EDGE);
201 if (aSubs.size() == 1) {
202 GeomEdgePtr anEdge = aSubs.front()->edge();
203 if (anEdge->isCircle() || anEdge->isEllipse()) {
204 processEdge(theVals, anEdge);
205 isCommonCase = false;
206 setShapeType("Disk");
210 // Check face bounded by a single wire which is rectangle
211 aSubs = theFace->subShapes(GeomAPI_Shape::WIRE);
212 if (aSubs.size() == 1) {
213 std::list<GeomPointPtr> aCorners;
214 if (aSubs.front()->wire()->isRectangle(aCorners)) {
215 GeomPointPtr aBaseCorner = aCorners.front();
216 aCorners.pop_front();
218 double aWidth = aBaseCorner->distance(aCorners.front());
219 double aHeight = aBaseCorner->distance(aCorners.back());
221 setShapeType("Rectangle");
222 theVals.addPoint("Corner", aBaseCorner);
223 theVals.addDirection("Normal", aPlane->direction());
224 theVals.addGroupName("Dimensions");
225 theVals.addNamedValue("Width", aWidth);
226 theVals.addNamedValue("Height", aHeight);
227 isCommonCase = false;
233 setShapeType("Plane");
234 theVals.addPoint("Origin", aPlane->location());
235 theVals.addDirection("Normal", aPlane->direction());
239 else if (GeomSpherePtr aSphere = theFace->getSphere()) {
240 setShapeType("Sphere");
241 theVals.addPoint("Center", aSphere->center());
242 theVals.addGroupName("Dimensions");
243 theVals.addNamedValue("Radius", aSphere->radius());
246 else if (GeomCylinderPtr aCylinder = theFace->getCylinder())
248 setShapeType("Cylinder");
249 theVals.addPoint("Position", aCylinder->location());
250 theVals.addDirection("Axis", aCylinder->axis());
251 theVals.addGroupName("Dimensions");
252 theVals.addNamedValue("Radius", aCylinder->radius());
253 theVals.addNamedValue("Height", aCylinder->height());
256 else if (GeomConePtr aCone = theFace->getCone()) {
257 setShapeType("Cone");
258 theVals.addPoint("Position", aCone->location());
259 theVals.addDirection("Axis", aCone->axis());
260 theVals.addGroupName("Dimensions");
261 theVals.addNamedValue("Radius 1", aCone->radius1());
262 theVals.addNamedValue("Radius 2", aCone->radius2());
263 theVals.addNamedValue("Height", aCone->height());
267 else if (GeomTorusPtr aTorus = theFace->getTorus()) {
268 setShapeType("Torus");
269 theVals.addPoint("Center", aTorus->center());
270 theVals.addDirection("Axis", aTorus->direction());
271 theVals.addGroupName("Dimensions");
272 theVals.addNamedValue("Major radius", aTorus->majorRadius());
273 theVals.addNamedValue("Minor radius", aTorus->minorRadius());
277 setShapeType("Face");
280 GeomAlgoAPI_ShapeInfo::Values::Values(const GeomAlgoAPI_ShapeInfo::InfoType theType)
283 static GeomAlgoAPI_ShapeInfo::Translator* kDefaultTr = new GeomAlgoAPI_ShapeInfo::Translator;
288 GeomAlgoAPI_ShapeInfo::Values& GeomAlgoAPI_ShapeInfo::Values::operator<< (double theValue)
294 std::ostringstream aStr;
300 myVals.push_back(GeomAlgoAPI_InfoValue(theValue));
306 GeomAlgoAPI_ShapeInfo::Values& GeomAlgoAPI_ShapeInfo::Values::operator << (bool theValue)
311 myStr += myTr->translate(theValue ? "True" : "False");
314 myVals.push_back(GeomAlgoAPI_InfoValue(theValue));
320 GeomAlgoAPI_ShapeInfo::Values& GeomAlgoAPI_ShapeInfo::Values::operator<< (const char* theStr)
322 if (myType == TYPE_HTML)
323 myStr += myTr->translate(theStr);
327 void GeomAlgoAPI_ShapeInfo::Values::addPoint(const char* theTitle, const GeomPointPtr& thePoint)
333 std::ostringstream aStr;
334 aStr << "<b>" << myTr->translate(theTitle) << "</b>"
335 << "<br> X: " << thePoint->x()
336 << "<br> Y: " << thePoint->y()
337 << "<br> Z: " << thePoint->z() << "<br>";
342 myVals.push_back(GeomAlgoAPI_InfoValue(thePoint->x()));
343 myVals.push_back(GeomAlgoAPI_InfoValue(thePoint->y()));
344 myVals.push_back(GeomAlgoAPI_InfoValue(thePoint->z()));
349 void GeomAlgoAPI_ShapeInfo::Values::addDirection(const char* theTitle, const GeomDirPtr& theDir)
355 std::ostringstream aStr;
356 aStr << "<b>" << myTr->translate(theTitle) << "</b>"
357 << "<br> DX: " << theDir->x()
358 << "<br> DY: " << theDir->y()
359 << "<br> DZ: " << theDir->z() << "<br>";
364 myVals.push_back(GeomAlgoAPI_InfoValue(theDir->x()));
365 myVals.push_back(GeomAlgoAPI_InfoValue(theDir->y()));
366 myVals.push_back(GeomAlgoAPI_InfoValue(theDir->z()));
371 void GeomAlgoAPI_ShapeInfo::Values::addNamedValue(const char* theName, const double theValue)
377 std::ostringstream aStr;
378 aStr << myTr->translate(theName) << ": " << theValue << "<br>";
383 *this << theValue; // just value, no name
388 void GeomAlgoAPI_ShapeInfo::Values::addNamedValue(const char* theName, const bool theValue)
394 std::ostringstream aStr;
395 aStr << myTr->translate(theName) << ": " << (theValue ? "True" : "False") << "<br>";
400 *this << theValue; // just value, no name
405 void GeomAlgoAPI_ShapeInfo::Values::addGroupName(const char* theName)
407 if (myType == TYPE_HTML)
409 myStr += "<b>" + myTr->translate(theName) + "</b>" + "<br>";