1 // Copyright (C) 2014-2019 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_LengthDimension.hxx>
38 #include <AIS_ParallelRelation.hxx>
39 #include <AIS_PerpendicularRelation.hxx>
40 #include <AIS_RadiusDimension.hxx>
41 #include <AIS_Shape.hxx>
42 #include <AIS_FixRelation.hxx>
43 #include <Prs3d_PointAspect.hxx>
45 #include <Graphic3d_AspectLine3d.hxx>
47 const double tolerance = 1e-7;
49 const int CONSTRAINT_TEXT_HEIGHT = 28; /// the text height of the constraint
50 const int CONSTRAINT_TEXT_SELECTION_TOLERANCE = 20; /// the text selection tolerance
52 GeomAPI_AISObject::GeomAPI_AISObject()
53 : GeomAPI_Interface(new Handle(AIS_InteractiveObject)())
57 GeomAPI_AISObject::~GeomAPI_AISObject()
60 // This is necessary for correct deletion of Handle entity.
61 // Without this Handle does not decremented counter to 0
62 Handle(AIS_InteractiveObject) *anAIS = implPtr<Handle(AIS_InteractiveObject)>();
68 void GeomAPI_AISObject::createShape(std::shared_ptr<GeomAPI_Shape> theShape)
70 const TopoDS_Shape& aTDS =
71 (theShape && theShape->implPtr<TopoDS_Shape>()) ?
72 theShape->impl<TopoDS_Shape>() : TopoDS_Shape();
74 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
75 if (!anAIS.IsNull()) {
76 Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
78 // if the AIS object is displayed in the opened local context in some mode, additional
79 // AIS sub objects are created there. They should be rebuild for correct selecting.
80 // It is possible to correct it by closing local context before the shape set and opening
81 // after. Another workaround to thrown down the selection and reselecting the AIS.
82 // If there was a problem here, try the first solution with close/open local context.
85 aShapeAIS->Redisplay(Standard_True);
88 // Set default point as a '+' symbol
89 Handle(AIS_Shape) aShape = new AIS_Shape(aTDS);
90 Handle(Prs3d_Drawer) aDrawer = aShape->Attributes();
91 if (aDrawer->HasOwnPointAspect())
92 aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_PLUS);
94 aDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_YELLOW, 1.));
95 aDrawer->SetIsoOnPlane(false);
96 setImpl(new Handle(AIS_InteractiveObject)(aShape));
100 std::shared_ptr<GeomAPI_Shape> GeomAPI_AISObject::getShape() const
102 std::shared_ptr<GeomAPI_Shape> aResult;
104 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
105 if (!anAIS.IsNull()) {
106 Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
108 std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
109 aResult->setImpl(new TopoDS_Shape(aShapeAIS->Shape()));
113 return std::shared_ptr<GeomAPI_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(AIS_LengthDimension) aDimAIS = new AIS_LengthDimension(theStartPoint->impl<gp_Pnt>(),
144 theEndPoint->impl<gp_Pnt>(),
145 thePlane->impl<gp_Pln>());
146 aDimAIS->SetCustomValue(theDistance);
148 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
149 anAspect->MakeArrows3d(Standard_False);
150 anAspect->MakeText3d(Standard_False);
151 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
152 anAspect->MakeTextShaded(Standard_True);
153 anAspect->ArrowAspect()->SetLength(theDistance / 10.);
154 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
155 aDimAIS->SetDimensionAspect(anAspect);
156 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
157 aDimAIS->SetFlyout(aFlyout);
159 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
161 // update presentation
162 Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
163 if (!aDimAIS.IsNull()) {
164 aDimAIS->SetMeasuredGeometry(theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(),
165 thePlane->impl<gp_Pln>());
166 aDimAIS->SetCustomValue(theDistance);
167 aDimAIS->SetFlyout(aFlyout);
169 aDimAIS->Redisplay(Standard_True);
174 bool GeomAPI_AISObject::isEmptyDistanceGeometry()
176 bool anEmpty = false;
178 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
179 if (!anAIS.IsNull()) {
180 Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
181 if (!aDimAIS.IsNull()) {
182 anEmpty = !aDimAIS->IsValid();
189 void GeomAPI_AISObject::createRadius(std::shared_ptr<GeomAPI_Circ> theCircle,
190 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
193 std::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
195 // TODO: a bug in AIS_RadiusDimension:
196 // The anchor point can't be myCirc.Location() - an exception is raised.
197 // But we need exactly this case...
198 // We want to show a radius dimension starting from the circle centre and
199 // ending at the user-defined point.
200 // Also, if anchor point coincides with myP2, the radius dimension is not displayed at all.
201 std::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
202 std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
203 anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
204 std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
205 const double aDelta = 1e-3;
206 anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
207 anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
208 anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
210 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
211 if (anAIS.IsNull()) {
212 Handle(AIS_RadiusDimension) aDimAIS = new AIS_RadiusDimension(theCircle->impl<gp_Circ>(),
213 anAnchor->impl<gp_Pnt>());
214 aDimAIS->SetCustomValue(theRadius);
216 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
217 anAspect->MakeArrows3d(Standard_False);
218 anAspect->MakeText3d(false);
219 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
220 anAspect->ArrowAspect()->SetLength(theRadius / 5.);
221 anAspect->MakeTextShaded(false);
222 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
223 aDimAIS->SetDimensionAspect(anAspect);
224 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
226 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
228 // update presentation
229 Handle(AIS_RadiusDimension) aDimAIS = Handle(AIS_RadiusDimension)::DownCast(anAIS);
230 if (!aDimAIS.IsNull()) {
231 aDimAIS->SetMeasuredGeometry(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
232 aDimAIS->SetCustomValue(theRadius);
233 aDimAIS->Redisplay(Standard_True);
238 void GeomAPI_AISObject::createParallel(std::shared_ptr<GeomAPI_Shape> theLine1,
239 std::shared_ptr<GeomAPI_Shape> theLine2,
240 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
241 std::shared_ptr<GeomAPI_Pln> thePlane)
243 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
244 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
245 if (anAIS.IsNull()) {
246 Handle(AIS_ParallelRelation) aParallel = new AIS_ParallelRelation(
247 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
249 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
251 setImpl(new Handle(AIS_InteractiveObject)(aParallel));
253 Handle(AIS_ParallelRelation) aParallel = Handle(AIS_ParallelRelation)::DownCast(anAIS);
254 if (!aParallel.IsNull()) {
255 aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
256 aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
257 aParallel->SetPlane(aPlane);
259 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
260 aParallel->Redisplay(Standard_True);
265 void GeomAPI_AISObject::createPerpendicular(std::shared_ptr<GeomAPI_Shape> theLine1,
266 std::shared_ptr<GeomAPI_Shape> theLine2,
267 std::shared_ptr<GeomAPI_Pln> thePlane)
269 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
270 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
271 if (anAIS.IsNull()) {
272 Handle(AIS_PerpendicularRelation) aPerpendicular = new AIS_PerpendicularRelation(
273 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
275 setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
277 Handle(AIS_PerpendicularRelation) aPerpendicular = Handle(AIS_PerpendicularRelation)::DownCast(
279 if (!aPerpendicular.IsNull()) {
280 aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
281 aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
282 aPerpendicular->SetPlane(aPlane);
283 aPerpendicular->Redisplay(Standard_True);
289 void GeomAPI_AISObject::createFixed(std::shared_ptr<GeomAPI_Shape> theShape,
290 std::shared_ptr<GeomAPI_Pln> thePlane)
292 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
293 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
294 TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
295 Handle(AIS_FixRelation) aFixPrs;
296 if (anAIS.IsNull()) {
297 aFixPrs = new AIS_FixRelation(aShape, aPlane);
299 setImpl(new Handle(AIS_InteractiveObject)(aFixPrs));
301 aFixPrs = Handle(AIS_FixRelation)::DownCast(anAIS);
302 if (!aFixPrs.IsNull()) {
303 aFixPrs->SetFirstShape(aShape);
304 aFixPrs->SetPlane(aPlane);
305 aFixPrs->Redisplay(Standard_True);
308 if (!aFixPrs.IsNull()) {
310 BRepBndLib::Add(aShape, aBox);
311 double aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
312 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
313 gp_Pnt aXYZ1(aXmin, aXmax, aYmin);
314 gp_Pnt aXYZ2(aXmax, aYmax, aZmax);
315 double aDist = aXYZ1.Distance(aXYZ2);
316 if (aDist > Precision::Confusion()) {
317 aFixPrs->SetArrowSize(aDist/8.);
322 void GeomAPI_AISObject::setColor(const int& theColor)
324 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
327 Quantity_Color aColor((Quantity_NameOfColor) theColor);
328 Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
329 if (!aDimAIS.IsNull()) {
330 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
332 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
333 if (!aContext.IsNull())
334 aContext->SetColor(anAIS, aColor, false);
336 anAIS->SetColor(aColor);
339 double GeomAPI_AISObject::width()
342 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
343 if (!anAIS.IsNull()) {
344 aWidth = anAIS->Width();
349 bool GeomAPI_AISObject::setWidth(const double& theWidth)
351 bool isChanged = false;
352 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
353 if (!anAIS.IsNull()) {
354 isChanged = anAIS->Width() != theWidth;
356 anAIS->SetWidth(theWidth);
361 bool GeomAPI_AISObject::setColor(int theR, int theG, int theB)
363 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
366 Quantity_Color aColor(theR / 255., theG / 255., theB / 255., Quantity_TOC_RGB);
367 Quantity_Color aCurrentColor;
368 anAIS->Color(aCurrentColor);
369 // do not set the same color to the presentation
370 if (aColor.IsEqual(aCurrentColor))
373 Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
374 if (!aDimAIS.IsNull()) {
375 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
377 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
378 if (!aContext.IsNull())
379 aContext->SetColor(anAIS, aColor, false);
381 anAIS->SetColor(aColor);
385 void GeomAPI_AISObject::getColor(int& theR, int& theG, int& theB)
387 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
391 Quantity_Color aColor;
392 anAIS->Color(aColor);
393 theR = (int)(aColor.Red()*255.);
394 theG = (int)(aColor.Green()*255.);
395 theB = (int)(aColor.Blue()*255.);
398 bool GeomAPI_AISObject::setDeflection(const double theDeflection)
400 bool isModified = false;
401 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
402 if (!anAIS.IsNull()) {
403 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
404 if (!anAISShape.IsNull()) {
405 Standard_Real aCoefficient, aPreviousCoefficient;
406 anAISShape->OwnDeviationCoefficient(aCoefficient, aPreviousCoefficient);
407 if (fabs(aCoefficient-theDeflection) > Precision::Confusion()) {
409 anAISShape->SetOwnDeviationCoefficient(theDeflection);
410 Handle(Prs3d_Drawer) aDrawer = anAISShape->DynamicHilightAttributes();
411 if (!aDrawer.IsNull()) {
412 aDrawer->SetDeviationCoefficient(theDeflection);
414 // redisplay is necessary here to update presentation in all modes
415 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
416 // displayer, redisplay here will not be necessary. But performance should be checked.
417 anAISShape->Redisplay(Standard_True);
424 double GeomAPI_AISObject::getDeflection() const
426 double aDeflection = -1;
428 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
429 if (!anAIS.IsNull()) {
430 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
431 aDeflection = aDrawer->DeviationCoefficient();
436 bool GeomAPI_AISObject::setTransparency(const double theTransparency)
438 bool isModified = false;
439 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
440 if (!anAIS.IsNull()) {
441 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
442 if (!anAISShape.IsNull()) {
443 Standard_Real aPreviousValue = anAISShape->Transparency();
444 if (fabs(aPreviousValue - theTransparency) > Precision::Confusion()) {
445 anAISShape->SetTransparency(theTransparency);
446 //>SetOwnDeviationCoefficient(theTransparency);
448 // redisplay is necessary here to update presentation in all modes
449 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
450 // displayer, redisplay here will not be necessary. But performance should be checked.
451 anAISShape->Redisplay(Standard_True);
458 double GeomAPI_AISObject::getTransparency() const
460 double aTransparency = 0;
462 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
463 if (!anAIS.IsNull()) {
464 aTransparency = anAIS->Transparency();
466 return aTransparency;
470 bool GeomAPI_AISObject::empty() const
472 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
473 ->impl<Handle(AIS_InteractiveObject)>();
479 int GeomAPI_AISObject::getShapeType() const
481 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
482 ->impl<Handle(AIS_InteractiveObject)>();
483 if (!anAIS.IsNull()) {
484 Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast(anAIS);
485 if (!aAISShape.IsNull()) {
486 const TopoDS_Shape aShape = aAISShape->Shape();
487 if (!aShape.IsNull())
488 return aShape.ShapeType();
494 void GeomAPI_AISObject::setPointMarker(int theType, double theScale)
496 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
497 if (!anAIS.IsNull()) {
498 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
499 if (aDrawer->HasOwnPointAspect()) {
500 Handle(Prs3d_PointAspect) aPA = aDrawer->PointAspect();
501 aPA->SetTypeOfMarker((Aspect_TypeOfMarker)theType);
502 aPA->SetScale(theScale);
504 Quantity_NameOfColor aCol = Quantity_NOC_YELLOW;
505 aDrawer->SetPointAspect(new Prs3d_PointAspect((Aspect_TypeOfMarker)theType, aCol, theScale));
510 bool GeomAPI_AISObject::setLineStyle(int theStyle)
512 bool isChanged = false;
513 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
514 if (!anAIS.IsNull()) {
515 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
516 Handle(Prs3d_LineAspect) aLineAspect;
518 Aspect_TypeOfLine aType = (Aspect_TypeOfLine)theStyle;
519 if (aDrawer->HasOwnLineAspect()) {
520 aLineAspect = aDrawer->LineAspect();
522 if (aDrawer->HasOwnWireAspect()) {
523 aLineAspect = aDrawer->WireAspect();
525 if (!aLineAspect.IsNull()) {
526 Handle(Graphic3d_AspectLine3d) aGraphicAspect = aLineAspect->Aspect();
527 Aspect_TypeOfLine aCurrentType = aGraphicAspect->Type();
528 isChanged = aType != aCurrentType;
530 aLineAspect->SetTypeOfLine(aType);
537 bool GeomAPI_AISObject::setTransparensy(double theVal)
539 bool isChanged = false;
540 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
541 if (!anAIS.IsNull()) {
542 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
543 if (!aContext.IsNull()) {
544 double aCurrentValue = anAIS->Transparency();
545 isChanged = aCurrentValue != theVal;
547 aContext->SetTransparency(anAIS, theVal, false);
549 anAIS->SetTransparency(theVal);