0030520: VIS - IVtkTools_ShapePicker::GetPickPosition() returns incorrect point
[occt.git] / src / Prs3d / Prs3d.cxx
1 // Created on: 1993-08-27
2 // Created by: Jean-Louis FRENKEL
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Prs3d.hxx>
18
19 #include <Bnd_Box.hxx>
20 #include <BRepBndLib.hxx>
21 #include <gp_Pnt.hxx>
22 #include <Graphic3d_Group.hxx>
23 #include <Prs3d_Drawer.hxx>
24 #include <Prs3d_LineAspect.hxx>
25 #include <Prs3d_Root.hxx>
26 #include <TopoDS_Shape.hxx>
27 #include <Graphic3d_ArrayOfSegments.hxx>
28
29 //=======================================================================
30 //function : MatchSegment
31 //purpose  :
32 //=======================================================================
33 Standard_Boolean Prs3d::MatchSegment 
34                  (const Standard_Real X,
35                   const Standard_Real Y,
36                   const Standard_Real Z,
37                   const Standard_Real aDistance,
38                   const gp_Pnt& P1,
39                   const gp_Pnt& P2,
40                   Standard_Real& dist)
41 {
42   Standard_Real X1,Y1,Z1,X2,Y2,Z2;
43   P1.Coord(X1,Y1,Z1); P2.Coord(X2,Y2,Z2);
44   Standard_Real DX = X2-X1; 
45   Standard_Real DY = Y2-Y1; 
46   Standard_Real DZ = Z2-Z1;
47   Standard_Real Dist = DX*DX + DY*DY + DZ*DZ;
48   if (Dist == 0.) return Standard_False;
49   
50   Standard_Real Lambda = ((X-X1)*DX + (Y-Y1)*DY + (Z-Z1)*DZ)/Dist;
51   if ( Lambda < 0. || Lambda > 1. ) return Standard_False;
52   dist =  Abs(X-X1-Lambda*DX) +
53           Abs(Y-Y1-Lambda*DY) +
54           Abs(Z-Z1-Lambda*DZ);
55   return (dist < aDistance);
56 }
57
58 //=======================================================================
59 //function : GetDeflection
60 //purpose  :
61 //=======================================================================
62 Standard_Real Prs3d::GetDeflection (const TopoDS_Shape&         theShape,
63                                     const Handle(Prs3d_Drawer)& theDrawer)
64 {
65   if (theDrawer->TypeOfDeflection() != Aspect_TOD_RELATIVE)
66   {
67     return theDrawer->MaximalChordialDeviation();
68   }
69
70   Bnd_Box aBndBox;
71   BRepBndLib::Add (theShape, aBndBox, Standard_False);
72   if (aBndBox.IsVoid())
73   {
74     return theDrawer->MaximalChordialDeviation();
75   }
76   else if (aBndBox.IsOpen())
77   {
78     if (!aBndBox.HasFinitePart())
79     {
80       return theDrawer->MaximalChordialDeviation();
81     }
82     aBndBox = aBndBox.FinitePart();
83   }
84
85   Graphic3d_Vec3d aVecMin, aVecMax;
86   aBndBox.Get (aVecMin.x(), aVecMin.y(), aVecMin.z(), aVecMax.x(), aVecMax.y(), aVecMax.z());
87   const Graphic3d_Vec3d aDiag = aVecMax - aVecMin;
88   const Standard_Real aDeflection = aDiag.maxComp() * theDrawer->DeviationCoefficient() * 4.0;
89
90   // we store computed relative deflection of shape as absolute deviation coefficient
91   // in case relative type to use it later on for sub-shapes.
92   theDrawer->SetMaximalChordialDeviation (aDeflection);
93   return aDeflection;
94 }
95
96 //==================================================================
97 // function: PrimitivesFromPolylines
98 // purpose:
99 //==================================================================
100 Handle(Graphic3d_ArrayOfPrimitives) Prs3d::PrimitivesFromPolylines (const Prs3d_NListOfSequenceOfPnt& thePoints)
101 {
102   if (thePoints.IsEmpty())
103   {
104     return Handle(Graphic3d_ArrayOfPrimitives)();
105   }
106
107   Standard_Integer aNbVertices = 0;
108   for (Prs3d_NListOfSequenceOfPnt::Iterator anIt (thePoints); anIt.More(); anIt.Next())
109   {
110     aNbVertices += anIt.Value()->Length();
111   }
112   const Standard_Integer aSegmentEdgeNb = (aNbVertices - thePoints.Size()) * 2;
113   Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNbVertices, aSegmentEdgeNb);
114   for (Prs3d_NListOfSequenceOfPnt::Iterator anIt (thePoints); anIt.More(); anIt.Next())
115   {
116     const Handle(TColgp_HSequenceOfPnt)& aPoints = anIt.Value();
117
118     Standard_Integer aSegmentEdge = aSegments->VertexNumber() + 1;
119     aSegments->AddVertex (aPoints->First());
120     for (Standard_Integer aPntIter = aPoints->Lower() + 1; aPntIter <= aPoints->Upper(); ++aPntIter)
121     {
122       aSegments->AddVertex (aPoints->Value (aPntIter));
123       aSegments->AddEdge (  aSegmentEdge);
124       aSegments->AddEdge (++aSegmentEdge);
125     }
126   }
127
128   return aSegments;
129 }
130
131 //==================================================================
132 // function: AddPrimitivesGroup
133 // purpose:
134 //==================================================================
135 void Prs3d::AddPrimitivesGroup (const Handle(Prs3d_Presentation)& thePrs,
136                                 const Handle(Prs3d_LineAspect)&   theAspect,
137                                 Prs3d_NListOfSequenceOfPnt&       thePolylines)
138 {
139   Handle(Graphic3d_ArrayOfPrimitives) aPrims = Prs3d::PrimitivesFromPolylines (thePolylines);
140   thePolylines.Clear();
141   if (!aPrims.IsNull())
142   {
143     Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup (thePrs);
144     aGroup->SetPrimitivesAspect (theAspect->Aspect());
145     aGroup->AddPrimitiveArray (aPrims);
146   }
147 }