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 setImpl(new Handle(AIS_InteractiveObject)(aShape));
99 std::shared_ptr<GeomAPI_Shape> GeomAPI_AISObject::getShape() const
101 std::shared_ptr<GeomAPI_Shape> aResult;
103 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
104 if (!anAIS.IsNull()) {
105 Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
107 std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
108 aResult->setImpl(new TopoDS_Shape(aShapeAIS->Shape()));
112 return std::shared_ptr<GeomAPI_Shape>();
115 void GeomAPI_AISObject::createDistance(std::shared_ptr<GeomAPI_Pnt> theStartPoint,
116 std::shared_ptr<GeomAPI_Pnt> theEndPoint,
117 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
118 std::shared_ptr<GeomAPI_Pln> thePlane, double theDistance)
121 if (theFlyoutPoint) {
123 if (theStartPoint->distance(theEndPoint) < tolerance)
124 aDist = theStartPoint->distance(theFlyoutPoint);
126 std::shared_ptr<GeomAPI_Lin> aLine = std::shared_ptr<GeomAPI_Lin>(
127 new GeomAPI_Lin(theStartPoint, theEndPoint));
128 aDist = aLine->distance(theFlyoutPoint);
131 std::shared_ptr<GeomAPI_XYZ> aLineDir = theEndPoint->xyz()->decreased(theStartPoint->xyz());
132 std::shared_ptr<GeomAPI_XYZ> aFOutDir = theFlyoutPoint->xyz()->decreased(
133 theStartPoint->xyz());
134 std::shared_ptr<GeomAPI_XYZ> aNorm = thePlane->direction()->xyz();
135 if (aLineDir->cross(aFOutDir)->dot(aNorm) < 0)
140 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
141 if (anAIS.IsNull()) {
142 Handle(AIS_LengthDimension) aDimAIS = new AIS_LengthDimension(theStartPoint->impl<gp_Pnt>(),
143 theEndPoint->impl<gp_Pnt>(),
144 thePlane->impl<gp_Pln>());
145 aDimAIS->SetCustomValue(theDistance);
147 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
148 anAspect->MakeArrows3d(Standard_False);
149 anAspect->MakeText3d(Standard_False);
150 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
151 anAspect->MakeTextShaded(Standard_True);
152 anAspect->ArrowAspect()->SetLength(theDistance / 10.);
153 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
154 aDimAIS->SetDimensionAspect(anAspect);
155 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
156 aDimAIS->SetFlyout(aFlyout);
158 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
160 // update presentation
161 Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
162 if (!aDimAIS.IsNull()) {
163 aDimAIS->SetMeasuredGeometry(theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(),
164 thePlane->impl<gp_Pln>());
165 aDimAIS->SetCustomValue(theDistance);
166 aDimAIS->SetFlyout(aFlyout);
168 aDimAIS->Redisplay(Standard_True);
173 bool GeomAPI_AISObject::isEmptyDistanceGeometry()
175 bool anEmpty = false;
177 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
178 if (!anAIS.IsNull()) {
179 Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
180 if (!aDimAIS.IsNull()) {
181 anEmpty = !aDimAIS->IsValid();
188 void GeomAPI_AISObject::createRadius(std::shared_ptr<GeomAPI_Circ> theCircle,
189 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
192 std::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
194 // TODO: a bug in AIS_RadiusDimension:
195 // The anchor point can't be myCirc.Location() - an exception is raised.
196 // But we need exactly this case...
197 // We want to show a radius dimension starting from the circle centre and
198 // ending at the user-defined point.
199 // Also, if anchor point coincides with myP2, the radius dimension is not displayed at all.
200 std::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
201 std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
202 anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
203 std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
204 const double aDelta = 1e-3;
205 anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
206 anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
207 anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
209 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
210 if (anAIS.IsNull()) {
211 Handle(AIS_RadiusDimension) aDimAIS = new AIS_RadiusDimension(theCircle->impl<gp_Circ>(),
212 anAnchor->impl<gp_Pnt>());
213 aDimAIS->SetCustomValue(theRadius);
215 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
216 anAspect->MakeArrows3d(Standard_False);
217 anAspect->MakeText3d(false);
218 anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
219 anAspect->ArrowAspect()->SetLength(theRadius / 5.);
220 anAspect->MakeTextShaded(false);
221 aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
222 aDimAIS->SetDimensionAspect(anAspect);
223 aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
225 setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
227 // update presentation
228 Handle(AIS_RadiusDimension) aDimAIS = Handle(AIS_RadiusDimension)::DownCast(anAIS);
229 if (!aDimAIS.IsNull()) {
230 aDimAIS->SetMeasuredGeometry(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
231 aDimAIS->SetCustomValue(theRadius);
232 aDimAIS->Redisplay(Standard_True);
237 void GeomAPI_AISObject::createParallel(std::shared_ptr<GeomAPI_Shape> theLine1,
238 std::shared_ptr<GeomAPI_Shape> theLine2,
239 std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
240 std::shared_ptr<GeomAPI_Pln> thePlane)
242 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
243 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
244 if (anAIS.IsNull()) {
245 Handle(AIS_ParallelRelation) aParallel = new AIS_ParallelRelation(
246 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
248 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
250 setImpl(new Handle(AIS_InteractiveObject)(aParallel));
252 Handle(AIS_ParallelRelation) aParallel = Handle(AIS_ParallelRelation)::DownCast(anAIS);
253 if (!aParallel.IsNull()) {
254 aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
255 aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
256 aParallel->SetPlane(aPlane);
258 aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
259 aParallel->Redisplay(Standard_True);
264 void GeomAPI_AISObject::createPerpendicular(std::shared_ptr<GeomAPI_Shape> theLine1,
265 std::shared_ptr<GeomAPI_Shape> theLine2,
266 std::shared_ptr<GeomAPI_Pln> thePlane)
268 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
269 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
270 if (anAIS.IsNull()) {
271 Handle(AIS_PerpendicularRelation) aPerpendicular = new AIS_PerpendicularRelation(
272 theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
274 setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
276 Handle(AIS_PerpendicularRelation) aPerpendicular = Handle(AIS_PerpendicularRelation)::DownCast(
278 if (!aPerpendicular.IsNull()) {
279 aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
280 aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
281 aPerpendicular->SetPlane(aPlane);
282 aPerpendicular->Redisplay(Standard_True);
288 void GeomAPI_AISObject::createFixed(std::shared_ptr<GeomAPI_Shape> theShape,
289 std::shared_ptr<GeomAPI_Pln> thePlane)
291 Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
292 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
293 TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
294 Handle(AIS_FixRelation) aFixPrs;
295 if (anAIS.IsNull()) {
296 aFixPrs = new AIS_FixRelation(aShape, aPlane);
298 setImpl(new Handle(AIS_InteractiveObject)(aFixPrs));
300 aFixPrs = Handle(AIS_FixRelation)::DownCast(anAIS);
301 if (!aFixPrs.IsNull()) {
302 aFixPrs->SetFirstShape(aShape);
303 aFixPrs->SetPlane(aPlane);
304 aFixPrs->Redisplay(Standard_True);
307 if (!aFixPrs.IsNull()) {
309 BRepBndLib::Add(aShape, aBox);
310 double aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
311 aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
312 gp_Pnt aXYZ1(aXmin, aXmax, aYmin);
313 gp_Pnt aXYZ2(aXmax, aYmax, aZmax);
314 double aDist = aXYZ1.Distance(aXYZ2);
315 if (aDist > Precision::Confusion()) {
316 aFixPrs->SetArrowSize(aDist/8.);
321 void GeomAPI_AISObject::setColor(const int& theColor)
323 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
326 Quantity_Color aColor((Quantity_NameOfColor) theColor);
327 Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
328 if (!aDimAIS.IsNull()) {
329 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
331 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
332 if (!aContext.IsNull())
333 aContext->SetColor(anAIS, aColor, false);
335 anAIS->SetColor(aColor);
338 double GeomAPI_AISObject::width()
341 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
342 if (!anAIS.IsNull()) {
343 aWidth = anAIS->Width();
348 bool GeomAPI_AISObject::setWidth(const double& theWidth)
350 bool isChanged = false;
351 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
352 if (!anAIS.IsNull()) {
353 isChanged = anAIS->Width() != theWidth;
355 anAIS->SetWidth(theWidth);
360 bool GeomAPI_AISObject::setColor(int theR, int theG, int theB)
362 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
365 Quantity_Color aColor(theR / 255., theG / 255., theB / 255., Quantity_TOC_RGB);
366 Quantity_Color aCurrentColor;
367 anAIS->Color(aCurrentColor);
368 // do not set the same color to the presentation
369 if (aColor.IsEqual(aCurrentColor))
372 Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
373 if (!aDimAIS.IsNull()) {
374 aDimAIS->DimensionAspect()->SetCommonColor(aColor);
376 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
377 if (!aContext.IsNull())
378 aContext->SetColor(anAIS, aColor, false);
380 anAIS->SetColor(aColor);
384 void GeomAPI_AISObject::getColor(int& theR, int& theG, int& theB)
386 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
390 Quantity_Color aColor;
391 anAIS->Color(aColor);
392 theR = (int)(aColor.Red()*255.);
393 theG = (int)(aColor.Green()*255.);
394 theB = (int)(aColor.Blue()*255.);
397 bool GeomAPI_AISObject::setDeflection(const double theDeflection)
399 bool isModified = false;
400 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
401 if (!anAIS.IsNull()) {
402 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
403 if (!anAISShape.IsNull()) {
404 Standard_Real aCoefficient, aPreviousCoefficient;
405 anAISShape->OwnDeviationCoefficient(aCoefficient, aPreviousCoefficient);
406 if (fabs(aCoefficient-theDeflection) > Precision::Confusion()) {
408 anAISShape->SetOwnDeviationCoefficient(theDeflection);
409 Handle(Prs3d_Drawer) aDrawer = anAISShape->DynamicHilightAttributes();
410 if (!aDrawer.IsNull()) {
411 aDrawer->SetDeviationCoefficient(theDeflection);
413 // redisplay is necessary here to update presentation in all modes
414 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
415 // displayer, redisplay here will not be necessary. But performance should be checked.
416 anAISShape->Redisplay(Standard_True);
423 double GeomAPI_AISObject::getDeflection() const
425 double aDeflection = -1;
427 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
428 if (!anAIS.IsNull()) {
429 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
430 aDeflection = aDrawer->DeviationCoefficient();
435 bool GeomAPI_AISObject::setTransparency(const double theTransparency)
437 bool isModified = false;
438 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
439 if (!anAIS.IsNull()) {
440 Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast(anAIS);
441 if (!anAISShape.IsNull()) {
442 Standard_Real aPreviousValue = anAISShape->Transparency();
443 if (fabs(aPreviousValue - theTransparency) > Precision::Confusion()) {
444 anAISShape->SetTransparency(theTransparency);
445 //>SetOwnDeviationCoefficient(theTransparency);
447 // redisplay is necessary here to update presentation in all modes
448 // Standard True flag. Displayer uses Standard False flag. If it will be changed in
449 // displayer, redisplay here will not be necessary. But performance should be checked.
450 anAISShape->Redisplay(Standard_True);
457 double GeomAPI_AISObject::getTransparency() const
459 double aTransparency = 0;
461 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
462 if (!anAIS.IsNull()) {
463 aTransparency = anAIS->Transparency();
465 return aTransparency;
469 bool GeomAPI_AISObject::empty() const
471 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
472 ->impl<Handle(AIS_InteractiveObject)>();
478 int GeomAPI_AISObject::getShapeType() const
480 Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
481 ->impl<Handle(AIS_InteractiveObject)>();
482 if (!anAIS.IsNull()) {
483 Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast(anAIS);
484 if (!aAISShape.IsNull()) {
485 const TopoDS_Shape aShape = aAISShape->Shape();
486 if (!aShape.IsNull())
487 return aShape.ShapeType();
493 void GeomAPI_AISObject::setPointMarker(int theType, double theScale)
495 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
496 if (!anAIS.IsNull()) {
497 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
498 if (aDrawer->HasOwnPointAspect()) {
499 Handle(Prs3d_PointAspect) aPA = aDrawer->PointAspect();
500 aPA->SetTypeOfMarker((Aspect_TypeOfMarker)theType);
501 aPA->SetScale(theScale);
503 Quantity_NameOfColor aCol = Quantity_NOC_YELLOW;
504 aDrawer->SetPointAspect(new Prs3d_PointAspect((Aspect_TypeOfMarker)theType, aCol, theScale));
509 bool GeomAPI_AISObject::setLineStyle(int theStyle)
511 bool isChanged = false;
512 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
513 if (!anAIS.IsNull()) {
514 Handle(Prs3d_Drawer) aDrawer = anAIS->Attributes();
515 Handle(Prs3d_LineAspect) aLineAspect;
517 Aspect_TypeOfLine aType = (Aspect_TypeOfLine)theStyle;
518 if (aDrawer->HasOwnLineAspect()) {
519 aLineAspect = aDrawer->LineAspect();
521 if (aDrawer->HasOwnWireAspect()) {
522 aLineAspect = aDrawer->WireAspect();
524 if (!aLineAspect.IsNull()) {
525 Handle(Graphic3d_AspectLine3d) aGraphicAspect = aLineAspect->Aspect();
526 Aspect_TypeOfLine aCurrentType = aGraphicAspect->Type();
527 isChanged = aType != aCurrentType;
529 aLineAspect->SetTypeOfLine(aType);
536 bool GeomAPI_AISObject::setTransparensy(double theVal)
538 bool isChanged = false;
539 Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
540 if (!anAIS.IsNull()) {
541 Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
542 if (!aContext.IsNull()) {
543 double aCurrentValue = anAIS->Transparency();
544 isChanged = aCurrentValue != theVal;
546 aContext->SetTransparency(anAIS, theVal, false);
548 anAIS->SetTransparency(theVal);