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 <GeomAPI_AISObject.h>
22 #include <GeomAPI_Circ.h>
23 #include <GeomAPI_Dir.h>
24 #include <GeomAPI_Lin.h>
25 #include <GeomAPI_Pln.h>
26 #include <GeomAPI_Pnt.h>
27 #include <GeomAPI_Shape.h>
28 #include <GeomAPI_XYZ.h>
30 #include <Geom_Plane.hxx>
31 #include <TopoDS_Shape.hxx>
32 #include <Quantity_NameOfColor.hxx>
33 #include <BRepBndLib.hxx>
35 #include <AIS_InteractiveObject.hxx>
36 #include <AIS_InteractiveContext.hxx>
37 #include <AIS_Shape.hxx>
38 #include <Prs3d_PointAspect.hxx>
39 #include <PrsDim_Dimension.hxx>
40 #include <PrsDim_LengthDimension.hxx>
41 #include <PrsDim_ParallelRelation.hxx>
42 #include <PrsDim_PerpendicularRelation.hxx>
43 #include <PrsDim_RadiusDimension.hxx>
44 #include <PrsDim_FixRelation.hxx>
46 #include <Graphic3d_AspectLine3d.hxx>
48 const double tolerance = 1e-7;
50 const int CONSTRAINT_TEXT_HEIGHT = 28; /// the text height of the constraint
51 const int CONSTRAINT_TEXT_SELECTION_TOLERANCE = 20; /// the text selection tolerance
53 GeomAPI_AISObject::GeomAPI_AISObject()
54 : GeomAPI_Interface(new Handle(AIS_InteractiveObject)())
58 GeomAPI_AISObject::~GeomAPI_AISObject()
61 // This is necessary for correct deletion of Handle entity.
62 // Without this Handle does not decremented counter to 0
63 Handle(AIS_InteractiveObject) *anAIS = implPtr<Handle(AIS_InteractiveObject)>();
69 void GeomAPI_AISObject::createShape(std::shared_ptr<GeomAPI_Shape> theShape)
71 const TopoDS_Shape& aTDS =
72 (theShape && theShape->implPtr<TopoDS_Shape>()) ?
73 theShape->impl<TopoDS_Shape>() : TopoDS_Shape();
75 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
76 if (!anAIS.IsNull()) {
77 Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
79 // if the AIS object is displayed in the opened local context in some mode, additional
80 // AIS sub objects are created there. They should be rebuild for correct selecting.
81 // It is possible to correct it by closing local context before the shape set and opening
82 // after. Another workaround to thrown down the selection and reselecting the AIS.
83 // If there was a problem here, try the first solution with close/open local context.
86 aShapeAIS->Redisplay(Standard_True);
89 // Set default point as a '+' symbol
90 Handle(AIS_Shape) aShape = new AIS_Shape(aTDS);
91 Handle(Prs3d_Drawer) aDrawer = aShape->Attributes();
92 if (aDrawer->HasOwnPointAspect())
93 aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_PLUS);
95 aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_YELLOW, 1.));
96 aDrawer->SetIsoOnPlane(false);
97 setImpl(new Handle(AIS_InteractiveObject)(aShape));
101 std::shared_ptr<GeomAPI_Shape> GeomAPI_AISObject::getShape() const
103 std::shared_ptr<GeomAPI_Shape> aResult;
105 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
106 if (!anAIS.IsNull()) {
107 Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
109 aResult.reset(new GeomAPI_Shape);
110 aResult->setImpl(new TopoDS_Shape(aShapeAIS->Shape()));
116 void GeomAPI_AISObject::createDistance(std::shared_ptr<GeomAPI_Pnt> theStartPoint,
117 std::shared_ptr<GeomAPI_Pnt> theEndPoint,
118 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
119 std::shared_ptr<GeomAPI_Pln> thePlane, double theDistance)
122 if (theFlyoutPoint) {
124 if (theStartPoint->distance(theEndPoint) < tolerance)
125 aDist = theStartPoint->distance(theFlyoutPoint);
127 std::shared_ptr<GeomAPI_Lin> aLine = std::shared_ptr<GeomAPI_Lin>(
128 new GeomAPI_Lin(theStartPoint, theEndPoint));
129 aDist = aLine->distance(theFlyoutPoint);
132 std::shared_ptr<GeomAPI_XYZ> aLineDir = theEndPoint->xyz()->decreased(theStartPoint->xyz());
133 std::shared_ptr<GeomAPI_XYZ> aFOutDir = theFlyoutPoint->xyz()->decreased(
134 theStartPoint->xyz());
135 std::shared_ptr<GeomAPI_XYZ> aNorm = thePlane->direction()->xyz();
136 if (aLineDir->cross(aFOutDir)->dot(aNorm) < 0)
141 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
142 if (anAIS.IsNull()) {
143 Handle(PrsDim_LengthDimension) aDimAIS =
144 new PrsDim_LengthDimension(theStartPoint->impl<gp_Pnt>(),
145 theEndPoint->impl<gp_Pnt>(),
146 thePlane->impl<gp_Pln>());
147 aDimAIS->SetCustomValue(theDistance);
149 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
150 anAspect->MakeArrows3d(Standard_False);
151 anAspect->MakeText3d(Standard_False);
152 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
153 anAspect->MakeTextShaded(Standard_True);
154 anAspect->ArrowAspect()->SetLength(theDistance / 10.);
155 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
156 aDimAIS->SetDimensionAspect(anAspect);
157 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
158 aDimAIS->SetFlyout(aFlyout);
160 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
162 // update presentation
163 Handle(PrsDim_LengthDimension) aDimAIS = Handle(PrsDim_LengthDimension)::DownCast(anAIS);
164 if (!aDimAIS.IsNull()) {
165 aDimAIS->SetMeasuredGeometry(theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(),
166 thePlane->impl<gp_Pln>());
167 aDimAIS->SetCustomValue(theDistance);
168 aDimAIS->SetFlyout(aFlyout);
170 aDimAIS->Redisplay(Standard_True);
175 bool GeomAPI_AISObject::isEmptyDistanceGeometry()
177 bool anEmpty = false;
179 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
180 if (!anAIS.IsNull()) {
181 Handle(PrsDim_LengthDimension) aDimAIS = Handle(PrsDim_LengthDimension)::DownCast(anAIS);
182 if (!aDimAIS.IsNull()) {
183 anEmpty = !aDimAIS->IsValid();
190 void GeomAPI_AISObject::createRadius(std::shared_ptr<GeomAPI_Circ> theCircle,
191 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
194 std::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
196 // TODO: a bug in AIS_RadiusDimension:
197 // The anchor point can't be myCirc.Location() - an exception is raised.
198 // But we need exactly this case...
199 // We want to show a radius dimension starting from the circle centre and
200 // ending at the user-defined point.
201 // Also, if anchor point coincides with myP2, the radius dimension is not displayed at all.
202 std::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
203 std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
204 anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
205 std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
206 const double aDelta = 1e-3;
207 anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
208 anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
209 anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
211 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
212 if (anAIS.IsNull()) {
213 Handle(PrsDim_RadiusDimension) aDimAIS = new PrsDim_RadiusDimension(theCircle->impl<gp_Circ>(),
214 anAnchor->impl<gp_Pnt>());
215 aDimAIS->SetCustomValue(theRadius);
217 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
218 anAspect->MakeArrows3d(Standard_False);
219 anAspect->MakeText3d(false);
220 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
221 anAspect->ArrowAspect()->SetLength(theRadius / 5.);
222 anAspect->MakeTextShaded(false);
223 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
224 aDimAIS->SetDimensionAspect(anAspect);
225 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
227 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
229 // update presentation
230 Handle(PrsDim_RadiusDimension) aDimAIS = Handle(PrsDim_RadiusDimension)::DownCast(anAIS);
231 if (!aDimAIS.IsNull()) {
232 aDimAIS->SetMeasuredGeometry(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
233 aDimAIS->SetCustomValue(theRadius);
234 aDimAIS->Redisplay(Standard_True);
239 void GeomAPI_AISObject::createParallel(std::shared_ptr<GeomAPI_Shape> theLine1,
240 std::shared_ptr<GeomAPI_Shape> theLine2,
241 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
242 std::shared_ptr<GeomAPI_Pln> thePlane)
244 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
245 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
246 if (anAIS.IsNull()) {
247 Handle(PrsDim_ParallelRelation) aParallel = new PrsDim_ParallelRelation(
248 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
250 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
252 setImpl(new Handle(AIS_InteractiveObject)(aParallel));
254 Handle(PrsDim_ParallelRelation) aParallel = Handle(PrsDim_ParallelRelation)::DownCast(anAIS);
255 if (!aParallel.IsNull()) {
256 aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
257 aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
258 aParallel->SetPlane(aPlane);
260 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
261 aParallel->Redisplay(Standard_True);
266 void GeomAPI_AISObject::createPerpendicular(std::shared_ptr<GeomAPI_Shape> theLine1,
267 std::shared_ptr<GeomAPI_Shape> theLine2,
268 std::shared_ptr<GeomAPI_Pln> thePlane)
270 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
271 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
272 if (anAIS.IsNull()) {
273 Handle(PrsDim_PerpendicularRelation) aPerpendicular = new PrsDim_PerpendicularRelation(
274 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
276 setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
278 Handle(PrsDim_PerpendicularRelation) aPerpendicular =
279 Handle(PrsDim_PerpendicularRelation)::DownCast(anAIS);
280 if (!aPerpendicular.IsNull()) {
281 aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
282 aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
283 aPerpendicular->SetPlane(aPlane);
284 aPerpendicular->Redisplay(Standard_True);
290 void GeomAPI_AISObject::createFixed(std::shared_ptr<GeomAPI_Shape> theShape,
291 std::shared_ptr<GeomAPI_Pln> thePlane)
293 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
294 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
295 TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
296 Handle(PrsDim_FixRelation) aFixPrs;
297 if (anAIS.IsNull()) {
298 aFixPrs = new PrsDim_FixRelation(aShape, aPlane);
300 setImpl(new Handle(AIS_InteractiveObject)(aFixPrs));
302 aFixPrs = Handle(PrsDim_FixRelation)::DownCast(anAIS);
303 if (!aFixPrs.IsNull()) {
304 aFixPrs->SetFirstShape(aShape);
305 aFixPrs->SetPlane(aPlane);
306 aFixPrs->Redisplay(Standard_True);
309 if (!aFixPrs.IsNull()) {
311 BRepBndLib::Add(aShape, aBox);
312 double aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
313 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
314 gp_Pnt aXYZ1(aXmin, aXmax, aYmin);
315 gp_Pnt aXYZ2(aXmax, aYmax, aZmax);
316 double aDist = aXYZ1.Distance(aXYZ2);
317 if (aDist > Precision::Confusion()) {
318 aFixPrs->SetArrowSize(aDist/8.);
323 void GeomAPI_AISObject::setColor(const int& theColor)
325 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
328 Quantity_Color aColor((Quantity_NameOfColor) theColor);
329 Handle(PrsDim_Dimension) aDimAIS = Handle(PrsDim_Dimension)::DownCast(anAIS);
330 if (!aDimAIS.IsNull()) {
331 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
333 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
334 if (!aContext.IsNull())
335 aContext->SetColor(anAIS, aColor, false);
337 anAIS->SetColor(aColor);
340 double GeomAPI_AISObject::width()
343 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
344 if (!anAIS.IsNull()) {
345 aWidth = anAIS->Width();
350 bool GeomAPI_AISObject::setWidth(const double& theWidth)
352 bool isChanged = false;
353 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
354 if (!anAIS.IsNull()) {
355 isChanged = anAIS->Width() != theWidth;
357 anAIS->SetWidth(theWidth);
362 bool GeomAPI_AISObject::setColor(int theR, int theG, int theB)
364 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
367 Quantity_Color aColor(theR / 255., theG / 255., theB / 255., Quantity_TOC_RGB);
368 Quantity_Color aCurrentColor;
369 anAIS->Color(aCurrentColor);
370 // do not set the same color to the presentation
371 if (aColor.IsEqual(aCurrentColor))
374 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
375 Handle(PrsDim_Dimension) aDimAIS = Handle(PrsDim_Dimension)::DownCast(anAIS);
376 if (!aDimAIS.IsNull()) {
377 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
378 if (!aContext.IsNull())
379 aContext->Redisplay(aDimAIS, false);
382 if (!aContext.IsNull())
383 aContext->SetColor(anAIS, aColor, false);
385 anAIS->SetColor(aColor);
390 void GeomAPI_AISObject::getColor(int& theR, int& theG, int& theB)
392 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
396 Quantity_Color aColor;
397 anAIS->Color(aColor);
398 theR = (int)(aColor.Red()*255.);
399 theG = (int)(aColor.Green()*255.);
400 theB = (int)(aColor.Blue()*255.);
403 bool GeomAPI_AISObject::setDeflection(const double theDeflection)
405 bool isModified = false;
406 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
407 if (!anAIS.IsNull()) {
408 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
409 if (!anAISShape.IsNull()) {
410 Standard_Real aCoefficient, aPreviousCoefficient;
411 anAISShape->OwnDeviationCoefficient(aCoefficient, aPreviousCoefficient);
412 if (fabs(aCoefficient-theDeflection) > Precision::Confusion()) {
414 anAISShape->SetOwnDeviationCoefficient(theDeflection);
415 Handle(Prs3d_Drawer) aDrawer = anAISShape->DynamicHilightAttributes();
416 if (!aDrawer.IsNull()) {
417 aDrawer->SetDeviationCoefficient(theDeflection);
419 // redisplay is necessary here to update presentation in all modes
420 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
421 // displayer, redisplay here will not be necessary. But performance should be checked.
422 anAISShape->Redisplay(Standard_True);
429 double GeomAPI_AISObject::getDeflection() const
431 double aDeflection = -1;
433 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
434 if (!anAIS.IsNull()) {
435 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
436 aDeflection = aDrawer->DeviationCoefficient();
441 bool GeomAPI_AISObject::setTransparency(const double theTransparency)
443 bool isModified = false;
444 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
445 if (!anAIS.IsNull()) {
446 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
447 if (!anAISShape.IsNull()) {
448 Standard_Real aPreviousValue = anAISShape->Transparency();
449 if (fabs(aPreviousValue - theTransparency) > Precision::Confusion()) {
450 anAISShape->SetTransparency(theTransparency);
451 //>SetOwnDeviationCoefficient(theTransparency);
453 // redisplay is necessary here to update presentation in all modes
454 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
455 // displayer, redisplay here will not be necessary. But performance should be checked.
456 anAISShape->Redisplay(Standard_True);
463 double GeomAPI_AISObject::getTransparency() const
465 double aTransparency = 0;
467 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
468 if (!anAIS.IsNull()) {
469 aTransparency = anAIS->Transparency();
471 return aTransparency;
475 bool GeomAPI_AISObject::empty() const
477 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
478 ->impl<Handle(AIS_InteractiveObject)>();
484 int GeomAPI_AISObject::getShapeType() const
486 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
487 ->impl<Handle(AIS_InteractiveObject)>();
488 if (!anAIS.IsNull()) {
489 Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast(anAIS);
490 if (!aAISShape.IsNull()) {
491 const TopoDS_Shape aShape = aAISShape->Shape();
492 if (!aShape.IsNull())
493 return aShape.ShapeType();
499 void GeomAPI_AISObject::setPointMarker(int theType, double theScale)
501 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
502 if (!anAIS.IsNull()) {
503 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
504 if (aDrawer->HasOwnPointAspect()) {
505 Handle(Prs3d_PointAspect) aPA = aDrawer->PointAspect();
506 aPA->SetTypeOfMarker((Aspect_TypeOfMarker)theType);
507 aPA->SetScale(theScale);
509 Quantity_NameOfColor aCol = Quantity_NOC_YELLOW;
510 aDrawer->SetPointAspect(new Prs3d_PointAspect((Aspect_TypeOfMarker)theType, aCol, theScale));
515 bool GeomAPI_AISObject::setLineStyle(int theStyle)
517 bool isChanged = false;
518 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
519 if (!anAIS.IsNull()) {
520 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
521 Handle(Prs3d_LineAspect) aLineAspect;
523 Aspect_TypeOfLine aType = (Aspect_TypeOfLine)theStyle;
524 if (aDrawer->HasOwnLineAspect()) {
525 aLineAspect = aDrawer->LineAspect();
527 if (aDrawer->HasOwnWireAspect()) {
528 aLineAspect = aDrawer->WireAspect();
530 if (!aLineAspect.IsNull()) {
531 Handle(Graphic3d_AspectLine3d) aGraphicAspect = aLineAspect->Aspect();
532 Aspect_TypeOfLine aCurrentType = aGraphicAspect->Type();
533 isChanged = aType != aCurrentType;
535 aLineAspect->SetTypeOfLine(aType);
542 bool GeomAPI_AISObject::setTransparensy(double theVal)
544 bool isChanged = false;
545 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
546 if (!anAIS.IsNull()) {
547 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
548 if (!aContext.IsNull()) {
549 double aCurrentValue = anAIS->Transparency();
550 isChanged = aCurrentValue != theVal;
552 aContext->SetTransparency(anAIS, theVal, false);
554 anAIS->SetTransparency(theVal);