Salome HOME
updated copyright message
[modules/shaper.git] / src / SketchAPI / SketchAPI_ConstraintAngle.cpp
1 // Copyright (C) 2019-2023  CEA, EDF
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 "SketchAPI_ConstraintAngle.h"
21
22 #include <ModelHighAPI_Dumper.h>
23 #include <ModelHighAPI_Tools.h>
24
25 #include <GeomAPI_Angle2d.h>
26 #include <GeomAPI_Lin2d.h>
27
28 #include <SketchPlugin_ConstraintAngle.h>
29 #include <SketchPlugin_Line.h>
30
31 #include <SketcherPrs_Tools.h>
32
33 #include <cmath>
34
35 SketchAPI_ConstraintAngle::SketchAPI_ConstraintAngle(
36     const std::shared_ptr<ModelAPI_Feature> & theFeature)
37 : SketchAPI_Constraint(theFeature)
38 {
39   ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
40   if (aConstraint)
41     initialize();
42 }
43
44 static FeaturePtr getFeatureLine(DataPtr theData, const std::string& theAttribute)
45 {
46   FeaturePtr aLine;
47   if (!theData.get() || !theData->isValid()) /// essential check as it is called in openGl thread)
48     return aLine;
49
50   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
51     std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theData->attribute(theAttribute));
52   if (anAttr) {
53     FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object());
54     if (aFeature && aFeature->getKind() == SketchPlugin_Line::ID()) {
55       return aFeature;
56     }
57   }
58   return aLine;
59 }
60
61 static void calculatePossibleValuesOfAngle(FeaturePtr theFeature,
62     double& theAngleDirect, double& theAngleComplementary, double& theAngleBackward)
63 {
64   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
65   FeaturePtr aLineA = getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
66   FeaturePtr aLineB = getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
67
68   std::shared_ptr<GeomDataAPI_Point2D> aStartA = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
69     aLineA->attribute(SketchPlugin_Line::START_ID()));
70   std::shared_ptr<GeomDataAPI_Point2D> aEndA = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
71     aLineA->attribute(SketchPlugin_Line::END_ID()));
72   std::shared_ptr<GeomDataAPI_Point2D> aStartB = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
73     aLineB->attribute(SketchPlugin_Line::START_ID()));
74   std::shared_ptr<GeomDataAPI_Point2D> aEndB = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
75     aLineB->attribute(SketchPlugin_Line::END_ID()));
76
77   std::shared_ptr<GeomAPI_Angle2d> anAng(new GeomAPI_Angle2d(
78       aStartA->pnt(), aEndA->pnt(), aStartB->pnt(), aEndB->pnt()));
79   theAngleDirect = fabs(anAng->angleDegree());
80   theAngleComplementary = 180.0 - theAngleDirect;
81   theAngleBackward = 360.0 - theAngleDirect;
82 }
83
84 static std::string angleTypeToString(FeaturePtr theFeature)
85 {
86   static const double TOLERANCE = 1.e-7;
87   static const std::string THE_ANGLE_DIRECT("Direct");
88   static const std::string THE_ANGLE_SUPPLEMENTARY("Supplementary");
89   static const std::string THE_ANGLE_BACKWARD("Backward");
90
91   double anAngleDirect, anAngleComplmentary, anAngleBackward;
92   calculatePossibleValuesOfAngle(theFeature, anAngleDirect, anAngleComplmentary, anAngleBackward);
93
94   AttributeDoublePtr aValueAttr = theFeature->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
95   double aDirectDiff = fabs(aValueAttr->value() - anAngleDirect);
96   double aComplementaryDiff = fabs(aValueAttr->value() - anAngleComplmentary);
97   double aBackwardDiff = fabs(aValueAttr->value() - anAngleBackward);
98
99   AttributeIntegerPtr aTypeAttr = theFeature->integer(SketchPlugin_ConstraintAngle::TYPE_ID());
100   bool isDirect = aTypeAttr->value() == SketcherPrs_Tools::ANGLE_DIRECT;
101   bool isComplementary = aTypeAttr->value() == SketcherPrs_Tools::ANGLE_COMPLEMENTARY;
102   bool isBackward = aTypeAttr->value() == SketcherPrs_Tools::ANGLE_BACKWARD;
103
104   // find the minimal difference
105   std::string aType;
106   if (isDirect && aDirectDiff < TOLERANCE) {
107     aType = THE_ANGLE_DIRECT;
108   }
109   else if (isComplementary && aComplementaryDiff < TOLERANCE)
110     aType = THE_ANGLE_SUPPLEMENTARY;
111   else if (isBackward && aBackwardDiff < TOLERANCE)
112     aType = THE_ANGLE_BACKWARD;
113   else {
114     if (aComplementaryDiff < aDirectDiff && aComplementaryDiff < aBackwardDiff)
115       aType = THE_ANGLE_SUPPLEMENTARY;
116     else if (aBackwardDiff < aDirectDiff && aBackwardDiff < aComplementaryDiff)
117       aType = THE_ANGLE_BACKWARD;
118     else
119       aType = THE_ANGLE_DIRECT;
120   }
121   return aType;
122 }
123
124 void SketchAPI_ConstraintAngle::dump(ModelHighAPI_Dumper& theDumper) const
125 {
126   // postpone constraint until all its attributes be dumped
127   if (!areAllAttributesDumped(theDumper))
128     return;
129
130   // calculate angle value as it was just applied to the attributes
131   FeaturePtr aBase = feature();
132
133   const std::string& aSketchName = theDumper.parentName(aBase);
134   theDumper.name(aBase, false, true, true); // mark constraint as dumped
135   theDumper << aSketchName << "." << "setAngle(";
136
137   bool isFirstAttr = true;
138   for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
139     AttributeRefAttrPtr aRefAttr = aBase->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
140     if (aRefAttr && aRefAttr->isInitialized()) {
141       theDumper << (isFirstAttr ? "" : ", ") << aRefAttr;
142       isFirstAttr = false;
143     }
144   }
145
146   AttributeDoublePtr aValueAttr = aBase->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
147   if (aValueAttr && aValueAttr->isInitialized())
148     theDumper << ", " << aValueAttr;
149
150   std::string aType = angleTypeToString(aBase);
151   theDumper << ", type = \"" << aType << "\")" << std::endl;
152 }