0024762: Visualization - new interactive object AIS_ColoredShape with customized...
[occt.git] / src / AIS / AIS_ColoredShape.cxx
CommitLineData
ad3217cd 1// Created on: 2014-04-24
2// Created by: Kirill Gavrilov
3// Copyright (c) 2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <AIS_ColoredShape.hxx>
17
18#include <AIS_InteractiveContext.hxx>
19#include <BRep_Builder.hxx>
20#include <BRepTools.hxx>
21#include <gp_Pnt2d.hxx>
22#include <Graphic3d_AspectFillArea3d.hxx>
23#include <Graphic3d_AspectLine3d.hxx>
24#include <Graphic3d_Group.hxx>
25#include <Graphic3d_StructureManager.hxx>
26#include <Graphic3d_Texture2Dmanual.hxx>
27#include <Precision.hxx>
28#include <Prs3d_LineAspect.hxx>
29#include <Prs3d_IsoAspect.hxx>
30#include <Prs3d_Presentation.hxx>
31#include <Prs3d_ShadingAspect.hxx>
32#include <Prs3d_Root.hxx>
33#include <PrsMgr_PresentationManager3d.hxx>
34#include <Standard_ErrorHandler.hxx>
35#include <StdPrs_ShadedShape.hxx>
36#include <StdPrs_ToolShadedShape.hxx>
37#include <StdPrs_WFDeflectionShape.hxx>
38#include <StdPrs_WFShape.hxx>
39#include <TopExp_Explorer.hxx>
40#include <TopoDS.hxx>
41#include <TopoDS_Compound.hxx>
42#include <TopoDS_Iterator.hxx>
43
44IMPLEMENT_STANDARD_HANDLE (AIS_ColoredDrawer, AIS_Drawer)
45IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer, AIS_Drawer)
46
47IMPLEMENT_STANDARD_HANDLE (AIS_ColoredShape, AIS_Shape)
48IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape, AIS_Shape)
49
50//=======================================================================
51//function : AIS_ColoredShape
52//purpose :
53//=======================================================================
54AIS_ColoredShape::AIS_ColoredShape (const TopoDS_Shape& theShape)
55: AIS_Shape (theShape)
56{
57 // disable dedicated line aspects
58 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
59 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
60 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
61}
62
63//=======================================================================
64//function : AIS_ColoredShape
65//purpose :
66//=======================================================================
67AIS_ColoredShape::AIS_ColoredShape (const Handle(AIS_Shape)& theShape)
68: AIS_Shape (theShape->Shape())
69{
70 // disable dedicated line aspects
71 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
72 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
73 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
74 if (theShape->HasMaterial())
75 {
76 SetMaterial (theShape->Material());
77 }
78 if (theShape->HasColor())
79 {
80 SetColor (theShape->Color());
81 }
82 if (theShape->HasWidth())
83 {
84 SetWidth (theShape->Width());
85 }
86 if (theShape->IsTransparent())
87 {
88 SetTransparency (theShape->Transparency());
89 }
90}
91
92//=======================================================================
93//function : CustomAspects
94//purpose :
95//=======================================================================
96Handle(AIS_ColoredDrawer) AIS_ColoredShape::CustomAspects (const TopoDS_Shape& theShape)
97{
98 Handle(AIS_ColoredDrawer) aDrawer;
99 myShapeColors.Find (theShape, aDrawer);
100 if (aDrawer.IsNull())
101 {
102 aDrawer = new AIS_ColoredDrawer (myDrawer);
103 myShapeColors.Bind (theShape, aDrawer);
104 LoadRecomputable (AIS_WireFrame);
105 LoadRecomputable (AIS_Shaded);
106 }
107 return aDrawer;
108}
109
110//=======================================================================
111//function : ClearCustomAspects
112//purpose :
113//=======================================================================
114void AIS_ColoredShape::ClearCustomAspects()
115{
116 if (myShapeColors.IsEmpty())
117 {
118 return;
119 }
120 myShapeColors.Clear();
121 LoadRecomputable (AIS_WireFrame);
122 LoadRecomputable (AIS_Shaded);
123}
124
125//=======================================================================
126//function : UnsetCustomAspects
127//purpose :
128//=======================================================================
129void AIS_ColoredShape::UnsetCustomAspects (const TopoDS_Shape& theShape,
130 const Standard_Boolean theToUnregister)
131{
132 if (!myShapeColors.IsBound (theShape))
133 {
134 return;
135 }
136
137 LoadRecomputable (AIS_WireFrame);
138 LoadRecomputable (AIS_Shaded);
139 if (theToUnregister)
140 {
141 myShapeColors.UnBind (theShape);
142 return;
143 }
144
145 myShapeColors.ChangeFind (theShape) = new AIS_ColoredDrawer (myDrawer);
146}
147
148//=======================================================================
149//function : SetCustomColor
150//purpose :
151//=======================================================================
152void AIS_ColoredShape::SetCustomColor (const TopoDS_Shape& theShape,
153 const Quantity_Color& theColor)
154{
155 if (theShape.IsNull())
156 {
157 return;
158 }
159
160 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
161 setColor (aDrawer, theColor);
162 aDrawer->SetOwnColor (theColor);
163 LoadRecomputable (AIS_WireFrame);
164 LoadRecomputable (AIS_Shaded);
165}
166
167//=======================================================================
168//function : SetCustomWidth
169//purpose :
170//=======================================================================
171void AIS_ColoredShape::SetCustomWidth (const TopoDS_Shape& theShape,
172 const Standard_Real theLineWidth)
173{
174 if (theShape.IsNull())
175 {
176 return;
177 }
178
179 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
180 setWidth (CustomAspects (theShape), theLineWidth);
181 aDrawer->SetOwnWidth (theLineWidth);
182 LoadRecomputable (AIS_WireFrame);
183 LoadRecomputable (AIS_Shaded);
184}
185
186//=======================================================================
187//function : SetColor
188//purpose :
189//=======================================================================
190
191void AIS_ColoredShape::SetColor (const Quantity_Color& theColor)
192{
193 setColor (myDrawer, theColor);
194 myOwnColor = theColor;
195 hasOwnColor = Standard_True;
196 LoadRecomputable (AIS_WireFrame);
197 LoadRecomputable (AIS_Shaded);
198 for (DataMapOfShapeColor::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
199 {
200 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
201 if (aDrawer->HasOwnColor())
202 {
203 continue;
204 }
205
206 if (aDrawer->HasShadingAspect())
207 {
208 aDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
209 }
210 if (aDrawer->HasLineAspect())
211 {
212 aDrawer->LineAspect()->SetColor (theColor);
213 }
214 if (aDrawer->HasWireAspect())
215 {
216 aDrawer->WireAspect()->SetColor (theColor);
217 }
218 }
219}
220
221//=======================================================================
222//function : SetWidth
223//purpose :
224//=======================================================================
225
226void AIS_ColoredShape::SetWidth (const Standard_Real theLineWidth)
227{
228 setWidth (myDrawer, theLineWidth);
229 myOwnWidth = theLineWidth;
230 LoadRecomputable (AIS_WireFrame);
231 LoadRecomputable (AIS_Shaded);
232 for (DataMapOfShapeColor::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
233 {
234 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
235 if (aDrawer->HasOwnWidth())
236 {
237 continue;
238 }
239
240 if (aDrawer->HasLineAspect())
241 {
242 aDrawer->LineAspect()->SetWidth (theLineWidth);
243 }
244 if (aDrawer->HasWireAspect())
245 {
246 aDrawer->WireAspect()->SetWidth (theLineWidth);
247 }
248 }
249}
250
251//=======================================================================
252//function : SetTransparency
253//purpose :
254//=======================================================================
255
256void AIS_ColoredShape::SetTransparency (const Standard_Real theValue)
257{
258 setTransparency (myDrawer, theValue);
259 myTransparency = theValue;
260 LoadRecomputable (AIS_WireFrame);
261 LoadRecomputable (AIS_Shaded);
262 for (DataMapOfShapeColor::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
263 {
264 const Handle(AIS_Drawer)& aDrawer = anIter.Value();
265 if (aDrawer->HasShadingAspect())
266 {
267 aDrawer->ShadingAspect()->SetTransparency (theValue, myCurrentFacingModel);
268 }
269 }
270}
271
272//=======================================================================
273//function : Compute
274//purpose :
275//=======================================================================
276void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
277 const Handle(Prs3d_Presentation)& thePrs,
278 const Standard_Integer theMode)
279{
280 thePrs->Clear();
281 if (IsInfinite())
282 {
283 thePrs->SetInfiniteState (Standard_True);
284 }
285
286 const Standard_Boolean isClosed = StdPrs_ToolShadedShape::IsClosed (myshape);
287 if (theMode == AIS_Shaded)
288 {
289 // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
290 Standard_Real anAnglePrev, anAngleNew, aCoeffPrev, aCoeffNew;
291 Standard_Boolean isOwnDeviationAngle = OwnDeviationAngle (anAngleNew, anAnglePrev);
292 Standard_Boolean isOwnDeviationCoefficient = OwnDeviationCoefficient(aCoeffNew, aCoeffPrev);
293 if ((isOwnDeviationAngle && Abs (anAngleNew - anAnglePrev) > Precision::Angular())
294 || (isOwnDeviationCoefficient && Abs (aCoeffNew - aCoeffPrev) > Precision::Confusion()))
295 {
296 BRepTools::Clean (myshape);
297 }
298 StdPrs_ShadedShape::Tessellate (myshape, myDrawer);
299 }
300
301 // 1) myShapeColors + myshape --> array[TopAbs_ShapeEnum] of map of color-to-compound
302 DataMapOfShapeCompd aTypeKeyshapeDrawshapeArray[(size_t )TopAbs_SHAPE];
303 dispatchColors (myshape, myShapeColors, aTypeKeyshapeDrawshapeArray);
304
305 // 2) finally add appropriate presentations (1 color -- 1 compound) according to theMode
306 Handle(AIS_ColoredDrawer) aCustomDrawer;
307 for (size_t aShType = 0; aShType < (size_t )TopAbs_SHAPE; ++aShType)
308 {
309 DataMapOfShapeCompd& aKeyshapeDrawshapeMap = aTypeKeyshapeDrawshapeArray[aShType];
310 for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap);
311 aMapIter.More(); aMapIter.Next())
312 {
313 const TopoDS_Shape& aShapeKey = aMapIter.Key(); // key shape with detailed color or a base shape
314 const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
315 Handle(AIS_Drawer) aDrawer = !myShapeColors.Find (aShapeKey, aCustomDrawer) ? myDrawer : aCustomDrawer;
316
317 // Draw each kind of subshapes and personal-colored shapes in a separate group
318 // since it's necessary to set transparency/material for all subshapes
319 // without affecting their unique colors
320 Handle(Graphic3d_Group) aCurrGroup = Prs3d_Root::NewGroup (thePrs);
321 switch (theMode)
322 {
323 default:
324 case AIS_Shaded:
325 {
326 if ((Standard_Integer )aShapeDraw.ShapeType() <= TopAbs_FACE
327 && !IsInfinite())
328 {
329 StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer);
330
331 aDrawer->SetShadingAspectGlobal (Standard_False);
332 Handle(Graphic3d_AspectFillArea3d) anAsp = aDrawer->ShadingAspect()->Aspect();
333 isClosed ? anAsp->SuppressBackFace() : anAsp->AllowBackFace();
334 aCurrGroup->SetGroupPrimitivesAspect (anAsp);
335 break;
336 }
337 // compute wire-frame otherwise
338 }
339 case AIS_WireFrame:
340 {
341 StdPrs_WFDeflectionShape::Add (thePrs, aShapeDraw, aDrawer);
342 break;
343 }
344 }
345 }
346 }
347}
348
349//=======================================================================
350//function : dispatchColors
351//purpose :
352//=======================================================================
353Standard_Boolean AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseKey,
354 const TopoDS_Shape& theSubshapeToParse,
355 const DataMapOfShapeShape& theSubshapeKeyshapeMap,
356 const TopAbs_ShapeEnum theParentType,
357 DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
358{
359 TopAbs_ShapeEnum aShType = theSubshapeToParse.ShapeType();
360 if (aShType == TopAbs_SHAPE)
361 {
362 return Standard_False;
363 }
364
365 // check own setting of current shape
366 TopoDS_Shape aKeyShape = theBaseKey;
367 Standard_Boolean isOverriden = theSubshapeKeyshapeMap.Find (theSubshapeToParse, aKeyShape);
368
369 // iterate on sub-shapes
370 BRep_Builder aBBuilder;
371 TopoDS_Shape aShapeCopy = theSubshapeToParse.EmptyCopied();
372 Standard_Boolean isSubOverride = Standard_False;
373 Standard_Integer nbDef = 0;
374 for (TopoDS_Iterator it (theSubshapeToParse); it.More(); it.Next())
375 {
376 if (dispatchColors (theBaseKey, it.Value(),
377 theSubshapeKeyshapeMap, aShType,
378 theTypeKeyshapeDrawshapeArray))
379 {
380 isSubOverride = Standard_True;
381 }
382 else
383 {
384 aBBuilder.Add (aShapeCopy, it.Value());
385 ++nbDef;
386 }
387 }
388 if (aShType == TopAbs_FACE || !isSubOverride)
389 {
390 aShapeCopy = theSubshapeToParse;
391 }
392 else if (nbDef == 0)
393 {
394 return isOverriden || isSubOverride; // empty compound
395 }
396
397 // if any of styles is overridden regarding to default one, add rest to map
398 if (isOverriden
399 || (isSubOverride && theParentType != TopAbs_WIRE // avoid drawing edges when vertex color is overridden
400 && theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
401 || (theParentType == TopAbs_SHAPE && !(isOverriden || isSubOverride))) // bind original shape to default color
402 {
403 TopoDS_Compound aCompound;
404 DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theTypeKeyshapeDrawshapeArray[(size_t )aShType];
405 if (!aKeyshapeDrawshapeMap.FindFromKey (aKeyShape, aCompound))
406 {
407 aBBuilder.MakeCompound (aCompound);
408 aKeyshapeDrawshapeMap.Add (aKeyShape, aCompound);
409 }
410 aBBuilder.Add (aCompound, aShapeCopy);
411 }
412 return isOverriden || isSubOverride;
413}
414
415//=======================================================================
416//function : dispatchColors
417//purpose :
418//=======================================================================
419void AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseShape,
420 const DataMapOfShapeColor& theKeyshapeColorMap,
421 DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
422{
423 // Extract <theShapeColors> map (KeyshapeColored -> Color)
424 // to subshapes map (Subshape -> KeyshapeColored).
425 // This needed when colored shape is not part of <theBaseShape>
426 // (but subshapes are) and actually container for subshapes.
427 DataMapOfShapeShape aSubshapeKeyshapeMap;
428 for (DataMapOfShapeColor::Iterator anIt (theKeyshapeColorMap);
429 anIt.More(); anIt.Next())
430 {
431 const TopoDS_Shape& aSh = anIt.Key();
432 TopAbs_ShapeEnum aType = aSh.ShapeType();
433 TopAbs_ShapeEnum aSubType = (aType == TopAbs_SOLID || aType == TopAbs_SHELL)
434 ? TopAbs_FACE
435 : (aType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_SHAPE);
436 switch (aSubType)
437 {
438 case TopAbs_SHAPE:
439 {
440 aSubshapeKeyshapeMap.Bind (aSh, aSh);
441 break;
442 }
443 default:
444 {
445 for (TopExp_Explorer anExp (aSh, aSubType); anExp.More(); anExp.Next())
446 {
447 if (!aSubshapeKeyshapeMap.IsBound (anExp.Current()))
448 {
449 aSubshapeKeyshapeMap.Bind (anExp.Current(), aSh);
450 }
451 }
452 }
453 }
454 }
455
456 // Fill the array of maps per shape type
457 dispatchColors (theBaseShape, theBaseShape,
458 aSubshapeKeyshapeMap, TopAbs_SHAPE,
459 theTypeKeyshapeDrawshapeArray);
460}