1 // Copyright (C) 2014-2020 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 "SketcherPrs_LengthDimension.h"
21 #include "SketcherPrs_Tools.h"
22 #include "SketcherPrs_DimensionStyle.h"
24 #include <SketchPlugin_Constraint.h>
25 #include <SketchPlugin_ConstraintLength.h>
26 #include <SketchPlugin_ConstraintDistance.h>
27 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
28 #include <SketchPlugin_ConstraintDistanceVertical.h>
29 #include <SketchPlugin_Line.h>
30 #include <SketchPlugin_Point.h>
31 #include <SketchPlugin_Circle.h>
33 #include <GeomDataAPI_Point2D.h>
34 #include <GeomAPI_Pnt.h>
35 #include <GeomAPI_XYZ.h>
36 #include <GeomAPI_Pnt2d.h>
37 #include <GeomAPI_Lin2d.h>
39 #include <ModelAPI_Data.h>
40 #include <ModelAPI_AttributeDouble.h>
41 #include <ModelAPI_AttributeInteger.h>
44 #define OCCT_28850_FIXED
46 /// Creates an aspect to be shown in length/radius dimension presentations
47 /// \return an instance of aspect
48 Handle(Prs3d_DimensionAspect) createDimensionAspect()
50 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
51 anAspect->MakeArrows3d(false);
52 anAspect->MakeText3d(false);
53 anAspect->MakeTextShaded(false);
54 anAspect->MakeUnitsDisplayed(false);
55 anAspect->TextAspect()->SetHeight(SketcherPrs_Tools::getConfigTextHeight());
56 anAspect->ArrowAspect()->SetLength(SketcherPrs_Tools::getArrowSize());
61 /// Update variable aspect parameters (depending on viewer scale)
62 /// \param theDimAspect an aspect to be changed
63 /// \param theDimValue an arrow value
64 /// \param theTextSize an arrow value
65 void updateArrows(Handle(Prs3d_DimensionAspect) theDimAspect,
66 double theDimValue, double theTextSize, SketcherPrs_Tools::LocationType theLocationType)
68 if (theLocationType == SketcherPrs_Tools::LOCATION_AUTOMATIC) {
69 double anArrowLength = theDimAspect->ArrowAspect()->Length();
70 // This is not realy correct way to get viewer scale.
71 double aViewerScale = (double) SketcherPrs_Tools::getConfigArrowSize() / anArrowLength;
73 if(theTextSize > ((theDimValue - 3 * SketcherPrs_Tools::getArrowSize()) * aViewerScale)) {
74 theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Left);
75 theDimAspect->SetArrowOrientation(Prs3d_DAO_External);
76 theDimAspect->SetExtensionSize(
77 (theTextSize / aViewerScale + SketcherPrs_Tools::getArrowSize()) / 2.0);
79 theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Center);
80 theDimAspect->SetArrowOrientation(Prs3d_DAO_Internal);
83 else if (theLocationType == SketcherPrs_Tools::LOCATION_RIGHT ||
84 theLocationType == SketcherPrs_Tools::LOCATION_LEFT) {
85 theDimAspect->SetTextHorizontalPosition(
86 theLocationType == SketcherPrs_Tools::LOCATION_LEFT ? Prs3d_DTHP_Left : Prs3d_DTHP_Right);
87 theDimAspect->SetArrowOrientation(Prs3d_DAO_External);
89 double anArrowLength = theDimAspect->ArrowAspect()->Length();
90 // This is not realy correct way to get viewer scale.
91 double aViewerScale = (double) SketcherPrs_Tools::getConfigArrowSize() / anArrowLength;
92 theDimAspect->SetExtensionSize(
93 (theTextSize / aViewerScale + SketcherPrs_Tools::getArrowSize()) / 2.0);
95 theDimAspect->TextAspect()->SetFont(Config_PropManager::string("Visualization",
96 "dimension_font").c_str());
98 theDimAspect->SetArrowTailSize(theDimAspect->ArrowAspect()->Length());
99 // The value of vertical aligment is sometimes changed
100 theDimAspect->TextAspect()->SetVerticalJustification(Graphic3d_VTA_CENTER);
104 static const gp_Pnt MyDefStart(0,0,0);
105 static const gp_Pnt MyDefEnd(1,0,0);
106 static const gp_Pln MyDefPln(gp_Pnt(0,0,0), gp_Dir(0,0,1));
108 IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_LengthDimension, AIS_LengthDimension);
110 SketcherPrs_LengthDimension::SketcherPrs_LengthDimension(ModelAPI_Feature* theConstraint,
111 SketchPlugin_Sketch* theSketcher)
112 : AIS_LengthDimension(MyDefStart, MyDefEnd, MyDefPln),
113 myConstraint(theConstraint),
114 mySketcher(theSketcher),
115 myFirstPoint(MyDefStart),
116 mySecondPoint(MyDefEnd),
119 myValue(0., false, "")
121 SetDimensionAspect(createDimensionAspect());
122 myStyleListener = new SketcherPrs_DimensionStyle();
124 setDirection(theConstraint, plane());
127 SketcherPrs_LengthDimension::~SketcherPrs_LengthDimension()
129 delete myStyleListener;
132 bool SketcherPrs_LengthDimension::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
133 const std::shared_ptr<GeomAPI_Ax3>& thePlane)
135 gp_Pnt2d aPnt1, aPnt2;
136 return readyToDisplay(theConstraint, thePlane, aPnt1, aPnt2);
139 static bool isEqualPoints(ModelAPI_Feature* theConstraint,
140 const gp_Pnt2d& theP1, const gp_Pnt2d& theP2)
142 bool isEqual = false;
143 if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
144 isEqual = Abs(theP1.X() - theP2.X()) < Precision::Confusion();
145 else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
146 isEqual = Abs(theP1.Y() - theP2.Y()) < Precision::Confusion();
148 isEqual = theP1.SquareDistance(theP2) < Precision::SquareConfusion();
153 void SketcherPrs_LengthDimension::Compute(
154 const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
155 const Handle(Prs3d_Presentation)& thePresentation,
156 const Standard_Integer theMode)
161 bool aReadyToDisplay = readyToDisplay(myConstraint, plane(), aP1, aP2);
162 if (aReadyToDisplay) {
163 if (isEqualPoints(myConstraint, aP1, aP2)) {
164 // adjust points to draw the dimension presentation
165 std::shared_ptr<GeomDataAPI_Dir> aDirAttr = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
166 myConstraint->attribute(SketchPlugin_ConstraintDistance::DIRECTION_ID()));
167 double x = 0.0, y = 0.0;
168 if (aDirAttr && aDirAttr->isInitialized()) {
171 if (x == 0.0 && y == 0.0)
174 else if (myConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
180 aP1.ChangeCoord().Add(aDir * (-Precision::Confusion()));
181 aP2.ChangeCoord().Add(aDir * Precision::Confusion());
184 myFirstPoint = plane()->to3D(aP1.X(), aP1.Y())->impl<gp_Pnt>();
185 mySecondPoint = plane()->to3D(aP2.X(), aP2.Y())->impl<gp_Pnt>();
187 myDistance = SketcherPrs_Tools::getFlyoutDistance(myConstraint);
188 myPlane = gp_Pln(plane()->impl<gp_Ax3>());
190 DataPtr aData = myConstraint->data();
191 AttributeDoublePtr anAttributeValue;
192 if (myConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
193 myConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
194 anAttributeValue = aData->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID());
196 anAttributeValue = aData->real(SketchPlugin_Constraint::VALUE());
197 myValue.init(anAttributeValue);
199 setDirection(myConstraint, plane());
202 // compute flyout distance
203 SetFlyout(myDistance);
204 SetMeasuredGeometry(myFirstPoint, mySecondPoint, myPlane);
206 // Update variable aspect parameters (depending on viewer scale)
207 double aTextSize = 0.0;
208 GetValueString(aTextSize);
210 std::string aLocationAttribute;
211 std::string aConstraintKind = myConstraint->getKind();
212 if (aConstraintKind == SketchPlugin_ConstraintLength::ID())
213 aLocationAttribute = SketchPlugin_ConstraintLength::LOCATION_TYPE_ID();
214 else if (aConstraintKind == SketchPlugin_ConstraintDistance::ID())
215 aLocationAttribute = SketchPlugin_ConstraintDistance::LOCATION_TYPE_ID();
216 else if (aConstraintKind == SketchPlugin_ConstraintDistanceHorizontal::ID())
217 aLocationAttribute = SketchPlugin_ConstraintDistanceHorizontal::LOCATION_TYPE_ID();
218 else if (aConstraintKind == SketchPlugin_ConstraintDistanceVertical::ID())
219 aLocationAttribute = SketchPlugin_ConstraintDistanceVertical::LOCATION_TYPE_ID();
221 AttributeIntegerPtr aLocAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>
222 (myConstraint->data()->attribute(aLocationAttribute));
223 SketcherPrs_Tools::LocationType aLocationType = aLocAttr->isInitialized() ?
224 (SketcherPrs_Tools::LocationType)(aLocAttr->value()) : SketcherPrs_Tools::LOCATION_AUTOMATIC;
225 updateArrows(DimensionAspect(), GetValue(), aTextSize, aLocationType);
227 // Update text visualization: parameter value or parameter text
228 myStyleListener->updateDimensions(this, myValue);
230 AIS_LengthDimension::Compute(thePresentationManager, thePresentation, theMode);
232 if (!aReadyToDisplay)
233 SketcherPrs_Tools::sendEmptyPresentationError(myConstraint,
234 "An empty AIS presentation: SketcherPrs_LengthDimension");
237 bool SketcherPrs_LengthDimension::readyToDisplay(ModelAPI_Feature* theConstraint,
238 const std::shared_ptr<GeomAPI_Ax3>& thePlane,
239 gp_Pnt2d& thePnt1, gp_Pnt2d& thePnt2)
244 DataPtr aData = theConstraint->data();
245 if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
246 // The constraint is length
247 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
248 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
249 (aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
253 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object());
254 if (!aFeature || aFeature->getKind() != SketchPlugin_Line::ID())
257 // Get geometry of the object
258 DataPtr aLineData = aFeature->data();
259 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
260 std::dynamic_pointer_cast<GeomDataAPI_Point2D>
261 (aLineData->attribute(SketchPlugin_Line::START_ID()));
262 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
263 std::dynamic_pointer_cast<GeomDataAPI_Point2D>
264 (aLineData->attribute(SketchPlugin_Line::END_ID()));
265 thePnt1 = gp_Pnt2d(aStartPoint->x(), aStartPoint->y());
266 thePnt2 = gp_Pnt2d(aEndPoint->x(), aEndPoint->y());
269 } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
270 theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
271 theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
272 // The constraint is distance
273 std::shared_ptr<GeomDataAPI_Point2D> aPoint_A = SketcherPrs_Tools::getFeaturePoint(
274 aData, SketchPlugin_Constraint::ENTITY_A(), thePlane);
275 std::shared_ptr<GeomDataAPI_Point2D> aPoint_B = SketcherPrs_Tools::getFeaturePoint(
276 aData, SketchPlugin_Constraint::ENTITY_B(), thePlane);
278 std::shared_ptr<GeomAPI_Pnt2d> aPnt_A;
279 std::shared_ptr<GeomAPI_Pnt2d> aPnt_B;
280 if (aPoint_A && aPoint_B) {
281 // Both objects are points
282 aPnt_A = aPoint_A->pnt();
283 aPnt_B = aPoint_B->pnt();
284 } else if (!aPoint_A && aPoint_B) {
285 // First object is line
286 FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
287 aData, SketchPlugin_Constraint::ENTITY_A());
289 aPnt_B = aPoint_B->pnt();
290 aPnt_A = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_B);
292 } else if (aPoint_A && !aPoint_B) {
293 // Second object is line
294 FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
295 aData, SketchPlugin_Constraint::ENTITY_B());
297 aPnt_A = aPoint_A->pnt();
298 aPnt_B = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_A);
301 if (!aPnt_A || !aPnt_B) // Objects not found
304 // Get points from these object
305 thePnt1 = gp_Pnt2d(aPnt_A->x(), aPnt_A->y());
306 thePnt2 = gp_Pnt2d(aPnt_B->x(), aPnt_B->y());
314 void SketcherPrs_LengthDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
315 const Standard_Integer theMode)
317 // Map the application selection modes to standard ones
318 Standard_Integer aMode;
320 case 0: // we should use selection of all objects
323 case SketcherPrs_Tools::Sel_Dimension_All:
326 case SketcherPrs_Tools::Sel_Dimension_Line:
329 case SketcherPrs_Tools::Sel_Dimension_Text:
333 // there are own selection modes, so the others should be ignored
334 // otherwise, the text selection appears in the viewer
338 SetSelToleranceForText2d(SketcherPrs_Tools::getArrowSize()/5.);
339 AIS_LengthDimension::ComputeSelection(aSelection, aMode);
342 void SketcherPrs_LengthDimension::setDirection(ModelAPI_Feature* theConstraint,
343 const std::shared_ptr<GeomAPI_Ax3>& thePlane)
345 #ifdef OCCT_28850_FIXED
346 if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
347 SetDirection(thePlane->dirX()->impl<gp_Dir>(), true);
348 else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
349 SetDirection(thePlane->dirY()->impl<gp_Dir>(), true);