1 {
2 *****************************************************************************
3 *                                                                           *
4 *  This file is part of the ZCAD                                            *
5 *                                                                           *
6 *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
7 *  for details about the copyright.                                         *
8 *                                                                           *
9 *  This program is distributed in the hope that it will be useful,          *
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
12 *                                                                           *
13 *****************************************************************************
14 }
15 {
16 @author(Andrey Zubarev <zamtmn@yandex.ru>)
17 }
18 
19 unit uzeentitiestree;
20 {$INCLUDE def.inc}
21 interface
22 uses
23     gzctnrvectortypes,graphics,gzctnrvectorsimple,gzctnrvectorpobjects,
24     uzbgeomtypes,gzctnrtree,uzgldrawcontext,uzegeometry,UGDBVisibleOpenArray,uzeentity,uzbtypesbase,uzbtypes,uzbmemman;
25 type
26 TZEntsManipulator=class;
27 TFirstStageData=record
28                   midlepoint:gdbvertex;
29                   d:double;
30                   counter:integer;
31                 end;
32 {EXPORT+}
33 TDrawType=(TDTFulDraw,TDTSimpleDraw);
34 TEntTreeNodeData=record
35                      infrustum:TActulity;
36                      nuldrawpos,minusdrawpos,plusdrawpos:TActulity;
37                      FulDraw:TDrawType;
38                      //nodedepth:GDBInteger;
39                      //pluscount,minuscount:GDBInteger;
40                  end;
41 TEntityArray=GZVectorPObects{GZVectorSimple}{-}<PGDBObjEntity,GDBObjEntity>{//}; {надо вынести куданить отдельно}
42          PTEntTreeNode=^TEntTreeNode;
43          TEntTreeNode={$IFNDEF DELPHI}packed{$ENDIF}object(GZBInarySeparatedGeometry{-}<TBoundingBox,DVector4D,TEntTreeNodeData,TZEntsManipulator,GDBObjEntity,PGDBObjEntity,TEntityArray>{//})
44                             procedure MakeTreeFrom(var entitys:GDBObjEntityOpenArray;AABB:TBoundingBox;const RN:Pointer);
45                             procedure DrawVolume(var DC:TDrawContext);
46                             procedure DrawNodeVolume(var DC:TDrawContext);
47                             procedure DrawWithAttribExternalArray(var DC:TDrawContext);
48                       end;
49 {EXPORT-}
50 TZEntsManipulator=class
51                    class procedure StoreTreeAdressInOnject(var Entity:GDBObjEntity;var Node:GZBInarySeparatedGeometry<TBoundingBox,DVector4D,TEntTreeNodeData,TZEntsManipulator,GDBObjEntity,PGDBObjEntity,TEntityArray>;const index:GDBInteger);
52                    class procedure CorrectNodeBoundingBox(var NodeBB:TBoundingBox;var Entity:GDBObjEntity);
GetEntityBoundingBoxnull53                    class function GetEntityBoundingBox(var Entity:GDBObjEntity):TBoundingBox;
GetBBPositionnull54                    class function GetBBPosition(const sep:DVector4D;const BB:TBoundingBox):TElemPosition;
isUnneedSeparatenull55                    class function isUnneedSeparate(const count,depth:integer):boolean;
GetTestNodesCountnull56                    class function GetTestNodesCount:integer;
57                    class procedure FirstStageCalcSeparatirs(var NodeBB:TBoundingBox;var Entity:GDBObjEntity;var PFirstStageData:pointer;TSM:TStageMode);
58                    class procedure CreateSeparator(var NodeBB:TBoundingBox;var TestNode:TEntTreeNode.TTestNode;var PFirstStageData:pointer;const NodeNum:integer);
IterateResult2PEntitynull59                    class function IterateResult2PEntity(const IterateResult:pointer):PGDBObjEntity;
StoreEntityToArraynull60                    class function StoreEntityToArray(var Entity:GDBObjEntity;var arr:TEntityArray):TArrayIndex;
61 
62                    {not used in generic, for external use}
63                    class procedure treerender(var Node:GZBInarySeparatedGeometry<TBoundingBox,DVector4D,TEntTreeNodeData,TZEntsManipulator,GDBObjEntity,PGDBObjEntity,TEntityArray>;var DC:TDrawContext);
64                   end;
65 TTestTreeArray=array [0..2] of TEntTreeNode.TTestNode;
66 var
67    SysVarRDSpatialNodeCount:integer=500;
68    SysVarRDSpatialNodesDepth:integer=16;
69    FirstStageData:TFirstStageData;
GetInNodeCountnull70 function GetInNodeCount(_InNodeCount:GDBInteger):GDBInteger;
71 implementation
72 procedure TEntTreeNode.DrawWithAttribExternalArray(var DC:TDrawContext);
73 var
74   pobj:pGDBObjEntity;
75   ir:itrec;
76 begin
77   pobj:=nul.beginiterate(ir);
78   if pobj<>nil then
79   repeat
80        pobj:=TZEntsManipulator.IterateResult2PEntity(pobj);
81        if pobj^.infrustum=dc.DrawingContext.infrustumactualy then
82                            pobj^.DrawWithAttrib(dc);
83        pobj:=nul.iterate(ir);
84   until pobj=nil;
85 end;
86 procedure TEntTreeNode.DrawNodeVolume(var DC:TDrawContext);
87 begin
88   dc.drawer.DrawAABB3DInModelSpace(BoundingBox,dc.DrawingContext.matrixs);
89 end;
90 procedure TEntTreeNode.DrawVolume;
91 begin
92      if assigned(pplusnode) then
93                        PTEntTreeNode(pplusnode)^.DrawVolume(dc);
94      if assigned(pminusnode) then
95                        PTEntTreeNode(pminusnode)^.DrawVolume(dc);
96      DrawNodeVolume(dc);
97 end;
98 class procedure TZEntsManipulator.treerender(var Node:GZBInarySeparatedGeometry<TBoundingBox,DVector4D,TEntTreeNodeData,TZEntsManipulator,GDBObjEntity,PGDBObjEntity,TEntityArray>;var DC:TDrawContext);
99 begin
100      begin
101        if (Node.NodeData.infrustum=dc.DrawingContext.InfrustumActualy) then
102        begin
103             if Node.NodeData.FulDraw=TDTFulDraw then
104             if (Node.NodeData.FulDraw=TDTFulDraw)or(Node.nul.count=0) then
105             begin
106             if assigned(Node.pminusnode)then
107                                             if (Node.NodeData.minusdrawpos<>dc.DrawingContext.DRAWCOUNT)or(dc.MaxDetail) then
108                                             begin
109                                                  treerender(Node.pminusnode^,dc);
110                                                  //PTEntTreeNode(Node.pminusnode)^.treerender(dc);
111                                                  Node.NodeData.minusdrawpos:=dc.DrawingContext.DRAWCOUNT
112                                             end;
113             if assigned(Node.pplusnode)then
114                                            if (Node.NodeData.plusdrawpos<>dc.DrawingContext.DRAWCOUNT)or(dc.MaxDetail) then
115                                            begin
116                                                 treerender(Node.pplusnode^,dc);
117                                                 //PTEntTreeNode(Node.pplusnode)^.treerender(dc);
118                                                 Node.NodeData.plusdrawpos:=dc.DrawingContext.DRAWCOUNT
119                                            end;
120             end;
121             begin
122                  if (Node.NodeData.FulDraw=TDTFulDraw)or(dc.MaxDetail) then
123                                                                       TEntTreeNode(Node).DrawWithAttribExternalArray(dc);
124                                                                       //GDBObjEntityOpenArray(Node.nul).DrawWithattrib(dc);
125                  Node.NodeData.nuldrawpos:=dc.DrawingContext.DRAWCOUNT;
126             end;
127        end;
128      end;
129 end;
TZEntsManipulator.StoreEntityToArraynull130 class function TZEntsManipulator.StoreEntityToArray(var Entity:GDBObjEntity;var arr:TEntityArray):TArrayIndex;
131 begin
132      result:=arr.pushBackData(@Entity);
133 end;
134 
TZEntsManipulator.isUnneedSeparatenull135 class function TZEntsManipulator.isUnneedSeparate(const count,depth:integer):boolean;
136 begin
137      if (Count<=GetInNodeCount(SysVarRDSpatialNodeCount))or(depth>=SysVarRDSpatialNodesDepth) then
138        result:=true
139      else
140        result:=false;
141 end;
TZEntsManipulator.GetTestNodesCountnull142 class function TZEntsManipulator.GetTestNodesCount:integer;
143 begin
144    result:=3;
145 end;
146 class procedure TZEntsManipulator.FirstStageCalcSeparatirs(var NodeBB:TBoundingBox;var Entity:GDBObjEntity;var PFirstStageData:pointer;TSM:TStageMode);
147 begin
148    case TSM of
149        TSMStart:begin
150                    FirstStageData.midlepoint:=NulVertex;
151                    FirstStageData.counter:=0;
152                    PFirstStageData:=@FirstStageData;
153                 end;
154 TSMAccumulation:begin
155                    FirstStageData.midlepoint:=vertexadd(Entity.vp.BoundingBox.LBN,FirstStageData.midlepoint);
156                    FirstStageData.midlepoint:=vertexadd(Entity.vp.BoundingBox.RTF,FirstStageData.midlepoint);
157                    inc(FirstStageData.counter,2);
158                 end;
159         TSMCalc:begin
160                    FirstStageData.midlepoint:=VertexMulOnSc(FirstStageData.midlepoint,1/FirstStageData.counter);
161                    FirstStageData.d:=sqrt(sqr(FirstStageData.midlepoint.x) + sqr(FirstStageData.midlepoint.y) + sqr(FirstStageData.midlepoint.z));
162                 end;
163          TSMEnd:begin
164                    PFirstStageData:=nil;
165                 end;
166    end;
167 end;
168 class procedure TZEntsManipulator.CreateSeparator(var NodeBB:TBoundingBox;var TestNode:TEntTreeNode.TTestNode;var PFirstStageData:pointer;const NodeNum:integer);
169 begin
170 case NodeNum of
171       0:TestNode.plane:=uzegeometry.PlaneFrom3Pont(FirstStageData.midlepoint,
172                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(x_Y_zVertex,FirstStageData.d)),
173                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(xy_Z_Vertex,FirstStageData.d))
174                                           );
175       1:TestNode.plane:=uzegeometry.PlaneFrom3Pont(FirstStageData.midlepoint,
176                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(_X_yzVertex,FirstStageData.d)),
177                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(xy_Z_Vertex,FirstStageData.d))
178                                           );
179       2:TestNode.plane:=uzegeometry.PlaneFrom3Pont(FirstStageData.midlepoint,
180                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(_X_yzVertex,FirstStageData.d)),
181                                           vertexadd(FirstStageData.midlepoint,VertexMulOnSc(x_Y_ZVertex,FirstStageData.d))
182                                           );
183 end;
184 end;
185 class procedure TZEntsManipulator.StoreTreeAdressInOnject(var Entity:GDBObjEntity;var Node:GZBInarySeparatedGeometry{-}<TBoundingBox,DVector4D,TEntTreeNodeData,TZEntsManipulator,GDBObjEntity,PGDBObjEntity,TEntityArray>;const index:GDBInteger);
186 begin
187   Entity.bp.TreePos.Owner:=@Node;
188   Entity.bp.TreePos.SelfIndex:=index;
189 end;
190 class procedure TZEntsManipulator.CorrectNodeBoundingBox(var NodeBB:TBoundingBox;var Entity:GDBObjEntity);
191 begin
192      ConcatBB(NodeBB,GetEntityBoundingBox(Entity));
193 end;
TZEntsManipulator.GetEntityBoundingBoxnull194 class function TZEntsManipulator.GetEntityBoundingBox(var Entity:GDBObjEntity):TBoundingBox;
195 begin
196      result:=Entity.vp.BoundingBox;
197 end;
198 
TZEntsManipulator.GetBBPositionnull199 class function TZEntsManipulator.GetBBPosition(const sep:DVector4D;const BB:TBoundingBox):TElemPosition;
200 var
201     d,d1,d2:double;
202 begin
203      d1:=sep[0] * BB.RTF.x + sep[1] * BB.RTF.y + sep[2] * BB.RTF.z + sep[3];
204      d2:=sep[0] * BB.LBN.x + sep[1] * BB.LBN.y + sep[2] * BB.LBN.z + sep[3];
205      if abs(d1)<eps then
206                         d1:=0;
207      if abs(d2)<eps then
208                         d2:=0;
209      d:=d1*d2;
210 
211      if d=0 then
212                 begin
213                      if (d1=0)and(d2=0) then
214                                             exit(TEP_nul)
215                                             //ta[i].nul.PushBackData(pobj)
216                 else if (d1>0)or(d2>0)  then
217                                             exit(TEP_Plus)
218                                             //ta[i].plus.PushBackData(pobj)
219                                         else
220                                             exit(TEP_Minus)
221                                             //ta[i].minus.PushBackData(pobj);
222                 end
223 else if d<0 then
224                 exit(TEP_nul)
225                 //ta[i].nul.PushBackData(pobj)
226 else if (d1>0)or(d2>0)  then
227                             exit(TEP_Plus)
228                             //ta[i].plus.PushBackData(pobj)
229                         else
230                             exit(TEP_Minus)
231                             //ta[i].minus.PushBackData(pobj);
232      //result:=TEP_nul;
233 end;
TZEntsManipulator.IterateResult2PEntitynull234 class function TZEntsManipulator.IterateResult2PEntity(const IterateResult:pointer):PGDBObjEntity;
235 begin
236   {if IterateResult<>nil then
237     result:=ppointer(IterateResult)^
238   else
239     result:=nil;}
240   result:=IterateResult;
241 end;
242 
243 procedure TEntTreeNode.MakeTreeFrom(var entitys:GDBObjEntityOpenArray;AABB:TBoundingBox;const RN:Pointer);
244 var
245     pobj:PGDBObjEntity;
246     ir:itrec;
247 begin
248      ClearSub;
249      Lock;
250      root:=rn;
251      pobj:=entitys.beginiterate(ir);
252      if pobj<>nil then
253        repeat
254          AddObjectToNodeTree(pobj^);
255          pobj:=entitys.iterate(ir);
256        until pobj=nil;
257      UnLock;
258      //createtree(entitys,AABB,nil,@self,nodedepth,TND_Root);
259 end;
GetInNodeCountnull260 function GetInNodeCount(_InNodeCount:GDBInteger):GDBInteger;
261 begin
262      if _InNodeCount>0 then
263                            result:=_InNodeCount
264                        else
265                            result:=500;
266 end;
267 begin
268 end.
269