Salome HOME
Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003)
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_EdgeWrapper.cpp
1 // Copyright (C) 2014-2019  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include <PlaneGCSSolver_EdgeWrapper.h>
21 #include <cmath>
22
23 static bool isLine(const GCSCurvePtr& theEntity)
24 {
25   return std::dynamic_pointer_cast<GCS::Line>(theEntity).get();
26 }
27
28 static bool isCircle(const GCSCurvePtr& theEntity)
29 {
30   return std::dynamic_pointer_cast<GCS::Circle>(theEntity).get();
31 }
32
33 static bool isArc(const GCSCurvePtr& theEntity)
34 {
35   return std::dynamic_pointer_cast<GCS::Arc>(theEntity).get();
36 }
37
38 static bool isEllipse(const GCSCurvePtr& theEntity)
39 {
40   return std::dynamic_pointer_cast<GCS::Ellipse>(theEntity).get();
41 }
42
43 static bool isEllipticArc(const GCSCurvePtr& theEntity)
44 {
45   return std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEntity).get();
46 }
47
48
49 PlaneGCSSolver_EdgeWrapper::PlaneGCSSolver_EdgeWrapper(const GCSCurvePtr theEntity)
50   : myEntity(theEntity)
51 {
52   if (isLine(myEntity))
53     myType = ENTITY_LINE;
54   else if (isArc(myEntity))
55     myType = ENTITY_ARC;
56   else if (isCircle(myEntity))
57     myType = ENTITY_CIRCLE;
58   else if (isEllipticArc(myEntity))
59     myType = ENTITY_ELLIPTICAL_ARC;
60   else if (isEllipse(myEntity))
61     myType = ENTITY_ELLIPSE;
62 }
63
64 static double squareDistance(const GCS::Point& theP1, const GCS::Point& theP2)
65 {
66   double dx = *theP1.x - *theP2.x;
67   double dy = *theP1.y - *theP2.y;
68   return dx*dx + dy*dy;
69 }
70
71 bool PlaneGCSSolver_EdgeWrapper::isDegenerated() const
72 {
73   static const double THE_SQ_TOL = tolerance * 1e-2;
74   static const double THE_ANGLE_TOL = 1.e-5;
75   static const double THE_MAX_RADIUS = 1e8;
76   static const double THE_SQ_MAX_RADIUS = THE_MAX_RADIUS * THE_MAX_RADIUS;
77
78   if (myType == ENTITY_LINE) {
79     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
80     return squareDistance(aLine->p1, aLine->p2) < THE_SQ_TOL;
81   }
82   else if (myType == ENTITY_CIRCLE) {
83     std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
84     return *aCircle->rad < tolerance || *aCircle->rad > THE_MAX_RADIUS;
85   }
86   else if (myType == ENTITY_ARC) {
87     std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(myEntity);
88     double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
89     double aSqRadius = squareDistance(anArc->center, anArc->start);
90     return aSqRadius < THE_SQ_TOL || aSqRadius > THE_SQ_MAX_RADIUS || // <- arc radius
91            anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
92   }
93   else if (myType == ENTITY_ELLIPSE) {
94     std::shared_ptr<GCS::Ellipse> anEllipse = std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
95     return *anEllipse->radmin < tolerance || anEllipse->getRadMaj() > THE_MAX_RADIUS;
96   }
97   else if (myType == ENTITY_ELLIPTICAL_ARC) {
98     std::shared_ptr<GCS::ArcOfEllipse> anArc =
99         std::dynamic_pointer_cast<GCS::ArcOfEllipse>(myEntity);
100     double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
101     return *anArc->radmin < THE_SQ_TOL || anArc->getRadMaj() > THE_SQ_MAX_RADIUS || // <- arc radius
102            anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
103   }
104   return false;
105 }