1 // Copyright (C) 2014-2017 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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <GeomAPI_AISObject.h>
23 #include <GeomAPI_Circ.h>
24 #include <GeomAPI_Dir.h>
25 #include <GeomAPI_Lin.h>
26 #include <GeomAPI_Pln.h>
27 #include <GeomAPI_Pnt.h>
28 #include <GeomAPI_Shape.h>
29 #include <GeomAPI_XYZ.h>
31 #include <Geom_Plane.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <Quantity_NameOfColor.hxx>
34 #include <BRepBndLib.hxx>
36 #include <AIS_InteractiveObject.hxx>
37 #include <AIS_InteractiveContext.hxx>
38 #include <AIS_LengthDimension.hxx>
39 #include <AIS_ParallelRelation.hxx>
40 #include <AIS_PerpendicularRelation.hxx>
41 #include <AIS_RadiusDimension.hxx>
42 #include <AIS_Shape.hxx>
43 #include <AIS_FixRelation.hxx>
44 #include <Prs3d_PointAspect.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 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 // redisplay is necessary here to update presentation in all modes
411 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
412 // displayer, redisplay here will not be necessary. But performance should be checked.
413 anAISShape->Redisplay(Standard_True);
420 double GeomAPI_AISObject::getDeflection() const
422 double aDeflection = -1;
424 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
425 if (!anAIS.IsNull()) {
426 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
427 aDeflection = aDrawer->DeviationCoefficient();
432 bool GeomAPI_AISObject::setTransparency(const double theTransparency)
434 bool isModified = false;
435 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
436 if (!anAIS.IsNull()) {
437 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
438 if (!anAISShape.IsNull()) {
439 Standard_Real aPreviousValue = anAISShape->Transparency();
440 if (fabs(aPreviousValue - theTransparency) > Precision::Confusion()) {
441 anAISShape->SetTransparency(theTransparency);
442 //>SetOwnDeviationCoefficient(theTransparency);
444 // redisplay is necessary here to update presentation in all modes
445 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
446 // displayer, redisplay here will not be necessary. But performance should be checked.
447 anAISShape->Redisplay(Standard_True);
454 double GeomAPI_AISObject::getTransparency() const
456 double aTransparency = 0;
458 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
459 if (!anAIS.IsNull()) {
460 aTransparency = anAIS->Transparency();
462 return aTransparency;
466 bool GeomAPI_AISObject::empty() const
468 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
469 ->impl<Handle(AIS_InteractiveObject)>();
475 int GeomAPI_AISObject::getShapeType() const
477 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
478 ->impl<Handle(AIS_InteractiveObject)>();
479 if (!anAIS.IsNull()) {
480 Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast(anAIS);
481 if (!aAISShape.IsNull()) {
482 const TopoDS_Shape aShape = aAISShape->Shape();
483 if (!aShape.IsNull())
484 return aShape.ShapeType();
490 void GeomAPI_AISObject::setPointMarker(int theType, double theScale)
492 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
493 if (!anAIS.IsNull()) {
494 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
495 if (aDrawer->HasOwnPointAspect()) {
496 Handle(Prs3d_PointAspect) aPA = aDrawer->PointAspect();
497 aPA->SetTypeOfMarker((Aspect_TypeOfMarker)theType);
498 aPA->SetScale(theScale);
500 Quantity_NameOfColor aCol = Quantity_NOC_YELLOW;
501 aDrawer->SetPointAspect(new Prs3d_PointAspect((Aspect_TypeOfMarker)theType, aCol, theScale));
506 bool GeomAPI_AISObject::setLineStyle(int theStyle)
508 bool isChanged = false;
509 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
510 if (!anAIS.IsNull()) {
511 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
512 Handle(Prs3d_LineAspect) aLineAspect;
514 Aspect_TypeOfLine aType = (Aspect_TypeOfLine)theStyle;
515 if (aDrawer->HasOwnLineAspect()) {
516 aLineAspect = aDrawer->LineAspect();
518 if (aDrawer->HasOwnWireAspect()) {
519 aLineAspect = aDrawer->WireAspect();
521 if (!aLineAspect.IsNull()) {
522 Handle(Graphic3d_AspectLine3d) aGraphicAspect = aLineAspect->Aspect();
523 Aspect_TypeOfLine aCurrentType = aGraphicAspect->Type();
524 isChanged = aType != aCurrentType;
526 aLineAspect->SetTypeOfLine(aType);
533 bool GeomAPI_AISObject::setTransparensy(double theVal)
535 bool isChanged = false;
536 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
537 if (!anAIS.IsNull()) {
538 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
539 if (!aContext.IsNull()) {
540 double aCurrentValue = anAIS->Transparency();
541 isChanged = aCurrentValue != theVal;
543 aContext->SetTransparency(anAIS, theVal, false);
545 anAIS->SetTransparency(theVal);