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 uzeentline;
20 {$INCLUDE def.inc}
21 
22 interface
23 uses LCLProc,uzeentityfactory,uzgldrawcontext,uzedrawingdef,uzecamera,
24      gzctnrvectorpobjects,uzestyleslayers,uzbtypesbase,uzeentsubordinated,
25      UGDBSelectedObjArray,uzeent3d,uzeentity,UGDBOpenArrayOfByte,uzbtypes,uzeconsts,
26      uzbgeomtypes,uzglviewareadata,uzegeometry,uzeffdxfsupport,uzbmemman;
27 type
28 {REGISTEROBJECTTYPE GDBObjLine}
29 {Export+}
30 PGDBObjLine=^GDBObjLine;
31 GDBObjLine={$IFNDEF DELPHI}packed{$ENDIF} object(GDBObj3d)
32                  CoordInOCS:GDBLineProp;(*'Coordinates OCS'*)(*saved_to_shd*)
33                  CoordInWCS:GDBLineProp;(*'Coordinates WCS'*)(*hidden_in_objinsp*)
34                  PProjPoint:PGDBLineProj;(*'Coordinates DCS'*)(*hidden_in_objinsp*)
35 
36                  constructor init(own:GDBPointer;layeraddres:PGDBLayerProp;LW:GDBSmallint;p1,p2:GDBvertex);
37                  constructor initnul(owner:PGDBObjGenericWithSubordinated);
38                  procedure LoadFromDXF(var f: GDBOpenArrayOfByte;ptu:PExtensionData;var drawing:TDrawingDef);virtual;
39 
40                  procedure SaveToDXF(var outhandle:{GDBInteger}GDBOpenArrayOfByte;var drawing:TDrawingDef;var IODXFContext:TIODXFContext);virtual;
41                  procedure FormatEntity(var drawing:TDrawingDef;var DC:TDrawContext);virtual;
42                  procedure CalcGeometry;virtual;
43                  procedure DrawGeometry(lw:GDBInteger;var DC:TDrawContext{infrustumactualy:TActulity;subrender:GDBInteger});virtual;
44                  procedure RenderFeedback(pcount:TActulity;var camera:GDBObjCamera; ProjectProc:GDBProjectProc;var DC:TDrawContext);virtual;
Clonenull45                   function Clone(own:GDBPointer):PGDBObjEntity;virtual;
46                  procedure rtedit(refp:GDBPointer;mode:GDBFloat;dist,wc:gdbvertex);virtual;
47                  procedure rtsave(refp:GDBPointer);virtual;
48                  procedure TransformAt(p:PGDBObjEntity;t_matrix:PDMatrix4D);virtual;
onmousenull49                   function onmouse(var popa:TZctnrVectorPGDBaseObjects;const MF:ClipArray;InSubEntry:GDBBoolean):GDBBoolean;virtual;
onpointnull50                   function onpoint(var objects:TZctnrVectorPGDBaseObjects;const point:GDBVertex):GDBBoolean;virtual;
51                  //procedure feedbackinrect;virtual;
InRectnull52                  //function InRect:TInRect;virtual;
53                   function getsnap(var osp:os_record; var pdata:GDBPointer; const param:OGLWndtype; ProjectProc:GDBProjectProc;SnapMode:TGDBOSMode):GDBBoolean;virtual;
getintersectnull54                   function getintersect(var osp:os_record;pobj:PGDBObjEntity; const param:OGLWndtype; ProjectProc:GDBProjectProc;SnapMode:TGDBOSMode):GDBBoolean;virtual;
55                 destructor done;virtual;
56                  procedure addcontrolpoints(tdesc:GDBPointer);virtual;
beforertmodifynull57                   function beforertmodify:GDBPointer;virtual;
58                   procedure clearrtmodify(p:GDBPointer);virtual;
59                  procedure rtmodifyonepoint(const rtmod:TRTModifyData);virtual;
IsRTNeedModifynull60                  function IsRTNeedModify(const Point:PControlPointDesc; p:GDBPointer):Boolean;virtual;
61                  procedure remaponecontrolpoint(pdesc:pcontrolpointdesc);virtual;
62                  procedure transform(const t_matrix:DMatrix4D);virtual;
jointolinenull63                   function jointoline(pl:pgdbobjline;var drawing:TDrawingDef):GDBBoolean;virtual;
64 
ObjToGDBStringnull65                   function ObjToGDBString(prefix,sufix:GDBString):GDBString;virtual;
GetObjTypeNamenull66                   function GetObjTypeName:GDBString;virtual;
GetCenterPointnull67                   function GetCenterPoint:GDBVertex;virtual;
68                   procedure getoutbound(var DC:TDrawContext);virtual;
CalcInFrustumnull69                   function CalcInFrustum(frustum:ClipArray;infrustumactualy:TActulity;visibleactualy:TActulity;var totalobj,infrustumobj:GDBInteger; ProjectProc:GDBProjectProc;const zoom,currentdegradationfactor:GDBDouble):GDBBoolean;virtual;
CalcTrueInFrustumnull70                   function CalcTrueInFrustum(frustum:ClipArray;visibleactualy:TActulity):TInBoundingVolume;virtual;
71 
IsIntersect_Linenull72                   function IsIntersect_Line(lbegin,lend:gdbvertex):Intercept3DProp;virtual;
73                   procedure AddOnTrackAxis(var posr:os_record;const processaxis:taddotrac);virtual;
GetTangentInPointnull74                   function GetTangentInPoint(point:GDBVertex):GDBVertex;virtual;
75 
CreateInstancenull76                   class function CreateInstance:PGDBObjLine;static;
GetObjTypenull77                   function GetObjType:TObjID;virtual;
78            end;
79 {Export-}
80 ptlinertmodify=^tlinertmodify;
81 tlinertmodify=record
82                     lbegin,lmidle,lend:GDBBoolean;
83                 end;
AllocAndInitLinenull84 function AllocAndInitLine(owner:PGDBObjGenericWithSubordinated):PGDBObjLine;
85 implementation
86 //uses log;
GDBObjLine.GetTangentInPointnull87 function GDBObjLine.GetTangentInPoint(point:GDBVertex):GDBVertex;
88 begin
89      result:=normalizevertex(VertexSub(CoordInWCS.lEnd,CoordInWCS.lBegin));
90 end;
91 procedure GDBObjLine.AddOnTrackAxis(var posr:os_record;const processaxis:taddotrac);
92 var tv,dir:gdbvertex;
93 begin
94      dir:=VertexSub(CoordInWCS.lEnd,CoordInWCS.lBegin);
95      processaxis(posr,dir);
96      //posr.arrayworldaxis.Add(@dir);
97      tv:=uzegeometry.vectordot(dir,zwcs);
98      processaxis(posr,tv);
99      //posr.arrayworldaxis.Add(@tv);
100 end;
GDBObjLine.IsIntersect_Linenull101 function GDBObjLine.IsIntersect_Line(lbegin,lend:gdbvertex):Intercept3DProp;
102 begin
103      result:=intercept3d(lbegin,lend,CoordInWCS.lBegin,CoordInWCS.lEnd);
104 end;
105 procedure GDBObjLine.getoutbound;
106 //var //tv,tv2:GDBVertex4D;
107     //t,b,l,r,n,f:GDBDouble;
108 begin
109      vp.BoundingBox:=CreateBBFrom2Point(CoordInWCS.lBegin,CoordInWCS.lEnd);
110 end;
GDBObjLine.GetCenterPointnull111 function GDBObjLine.GetCenterPoint;
112 begin
113      result:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 0.5);
114 end;
GDBObjLine.GetObjTypeNamenull115 function GDBObjLine.GetObjTypeName;
116 begin
117      result:=ObjN_GDBObjLine;
118 end;
GDBObjLine.jointolinenull119 function GDBObjLine.jointoline(pl:pgdbobjline;var drawing:TDrawingDef):GDBBoolean;
onlinenull120 function online(w,u:gdbvertex):GDBBoolean;
121 var ww:GDBDouble;
122     l:GDBDouble;
123 begin
124      ww:=scalardot(w,u);
125      l:=SqrOneVertexlength(VertexSub(w,VertexMulOnSc(u,ww)));
126      if eps>l then
127                   result:=true
128               else
129                   result:=false;
130 end;
131 var t1,t2,a1,a2:GDBDouble;
132     q:GDBBoolean;
133     w,u,dir:gdbvertex;
134     dc:TDrawContext;
135 begin
136      result:=false;
137      if Vertexlength(CoordInWCS.lbegin, CoordInWCS.lend)<Vertexlength(pl^.CoordInWCS.lbegin,pl^.CoordInWCS.lend) then
138      begin
139           result:=pl^.jointoline(@self,drawing);
140           exit;
141      end;
142      dir:=VertexSub(CoordInWCS.lEnd,CoordInWCS.lBegin);
143      u:=NormalizeVertex(dir);
144      w:=VertexSub(pl.coordinwcs.lbegin,coordinwcs.lbegin);
145      t1:=(scalardot(w,dir))/SqrOneVertexlength(dir);
146      q:=online(w,u);
147      w:=VertexSub(pl.coordinwcs.lend,coordinwcs.lbegin);
148      t2:=(scalardot(w,dir))/SqrOneVertexlength(dir);
149      q:=q and online(w,u);
150      if not q then exit;
151      a1:=0;
152      a2:=1;
153      if t1<a1 then a1:=t1;
154      if t2<a1 then a1:=t2;
155      if t1>a2 then a2:=t1;
156      if t2>a2 then a2:=t2;
157      self.CoordInOCS.lend:=VertexDmorph(self.CoordInOCS.lbegin,dir,a2);
158      self.CoordInOCS.lbegin:=VertexDmorph(self.CoordInOCS.lbegin,dir,a1);
159      self.CoordInWCS.lend:=VertexDmorph(self.CoordInWCS.lbegin,dir,a2);
160      self.CoordInWCS.lbegin:=VertexDmorph(self.CoordInWCS.lbegin,dir,a1);
161      dc:=drawing.CreateDrawingRC;
162      FormatEntity(drawing,dc);
163      pl^.YouDeleted(drawing);
164      result:=true;
165 end;
GDBObjLine.ObjToGDBStringnull166 function GDBObjLine.ObjToGDBString(prefix,sufix:GDBString):GDBString;
167 begin
168      result:=prefix+inherited ObjToGDBString('GDBObjLine (addr:',')')+sufix;
169 end;
170 constructor GDBObjLine.initnul;
171 begin
172   inherited initnul(owner);
173   bp.ListPos.Owner:=owner;
174   //vp.ID := GDBlineID;
175   CoordInOCS.lBegin := NulVertex;
176   CoordInOCS.lEnd := NulVertex;
177   PProjPoint:=nil;
178 end;
179 constructor GDBObjLine.init;
180 begin
181   inherited init(own,layeraddres, lw);
182   //vp.ID := GDBlineID;
183   CoordInOCS.lBegin := p1;
184   CoordInOCS.lEnd := p2;
185   PProjPoint:=nil;
186   //format;
187 end;
GDBObjLine.GetObjTypenull188 function GDBObjLine.GetObjType;
189 begin
190      result:=GDBlineID;
191 end;
192 procedure GDBObjLine.LoadFromDXF;
193 var //s: GDBString;
194   byt: GDBInteger;
195 begin
196   byt:=readmystrtoint(f);
197   while byt <> 0 do
198   begin
199     if not LoadFromDXFObjShared(f,byt,ptu,drawing) then
200        if not dxfvertexload(f,10,byt,CoordInOCS.lBegin) then
201           if not dxfvertexload(f,11,byt,CoordInOCS.lEnd) then {s := }f.readGDBSTRING;
202     byt:=readmystrtoint(f);
203   end;
204 end;
205 destructor GDBObjLine.done;
206 begin
207      if PProjPoint<>nil then
208                             GDBFreeMem(GDBPointer(PProjPoint));
209      inherited done;
210 end;
211 procedure GDBObjLine.CalcGeometry;
212 var m:DMatrix4D;
213 begin
214      if bp.ListPos.owner<>nil then
215                                     begin
216                                          if bp.ListPos.owner^.GetHandle=H_Root then
217                                                                                    begin
218                                                                                         CoordInWCS.lbegin:=CoordInOCS.lbegin;
219                                                                                         CoordInWCS.lend:=CoordInOCS.lend;
220                                                                                     end
221                                                                                else
222                                                                                    begin
223                                                                                          m:=bp.ListPos.owner^.GetMatrix^;
224                                                                                          CoordInWCS.lbegin:=VectorTransform3D(CoordInOCS.lbegin,m);
225                                                                                          CoordInWCS.lend:=VectorTransform3D(CoordInOCS.lend,m);
226                                                                                    end;
227                                     end
228                                 else
229                                     begin
230                                          CoordInWCS.lbegin:=CoordInOCS.lbegin;
231                                          CoordInWCS.lend:=CoordInOCS.lend;
232                                     end;
233 end;
234 
235 procedure GDBObjLine.FormatEntity(var drawing:TDrawingDef;var DC:TDrawContext);
236 begin
237   calcgeometry;
238   calcbb(dc);
239 
240   Representation.Clear;
241   Representation.DrawLineWithLT(dc,CoordInWCS.lBegin,CoordInWCS.lEnd,vp);
242 end;
GDBObjLine.CalcInFrustumnull243 function GDBObjLine.CalcInFrustum;
244 var i:GDBInteger;
245 begin
246       if CalcAABBInFrustum(vp.BoundingBox,frustum)<>IREmpty then
247                                                                                   result:=true
248                                                                               else
249                                                                                   result:=false;
250       exit;
251       result:=true;
252       for i:=0 to 5 do
253       begin
254       if(frustum[i][0] * CoordInWCS.lbegin.x + frustum[i][1] * CoordInWCS.lbegin.y + frustum[i][2] * CoordInWCS.lbegin.z + frustum[i][3] < 0 )
255      and(frustum[i][0] * CoordInWCS.lend.x +   frustum[i][1] * CoordInWCS.lend.y +   frustum[i][2] * CoordInWCS.lend.z +   frustum[i][3] < 0 )
256       then
257       begin
258            result:=false;
259            system.break;
260       end;
261       end;
262 end;
GDBObjLine.CalcTrueInFrustumnull263 function GDBObjLine.CalcTrueInFrustum;
264 begin
265       result:=Representation.CalcTrueInFrustum(frustum,true);
266 end;
GDBObjLine.onpointnull267 function GDBObjLine.onpoint(var objects:TZctnrVectorPGDBaseObjects;const point:GDBVertex):GDBBoolean;
268 begin
269      if {distance2piece}SQRdist_Point_to_Segment(point,self.CoordInWCS.lBegin,self.CoordInWCS.lEnd)<bigeps then
270                                                                                   begin
271                                                                                     result:=true;
272                                                                                     objects.PushBackData(@self);
273                                                                                   end
274                                                                                 else
275                                                                                     result:=false;
276 end;
277 
GDBObjLine.onmousenull278 function GDBObjLine.onmouse;
279 begin
280      if Representation.CalcTrueInFrustum(mf,false)<>IREmpty
281                                                                           then
282                                                                               result:=true
283                                                                           else
284                                                                               result:=false;
285 end;
286 procedure GDBObjLine.DrawGeometry;
287 //var
288 //  templod:gdbdouble;
289 begin
290   if (selected)or(dc.selected) then
291                      Representation.DrawNiceGeometry(DC)
292                  else
293                      begin
294                      Representation.DrawGeometry(DC);
295                      exit;
296                      end;
297   {if vp.LineType<>nil then
298      if vp.LineType.h>0 then
299   begin
300   templod:=(vp.LineType.h*vp.LineTypeScale*SysVar.dwg.DWG_LTScale^)/(dc.zoom);
301   if templod<3 then
302      begin
303      DC.Drawer.DrawLine3DInModelSpace(CoordInWCS.lBegin,CoordInWCS.lEnd,DC.matrixs);
304      end;
305   end;}
306   inherited;
307   {oglsm.myglbegin(GL_points);
308   myglVertex3dV(@CoordInWCS.lBegin);
309   myglVertex3dV(@CoordInWCS.lEnd);
310   oglsm.myglend;}
311 end;
312 procedure GDBObjLine.RenderFeedback;
313 var tv:GDBvertex;
314 //    ptv:PGDBvertex;
315 //    ptv2d:PGDBvertex2D;
316 //    i:GDBInteger;
317 begin
318   //if POGLWnd=nil then exit;
319   {if PProjPoint<>nil then
320   begin
321        GDBFreeMem(GDBPointer(PProjPoint));
322   end;}
323   if PProjPoint=nil then GDBGetMem({$IFDEF DEBUGBUILD}'{BC97B497-84C4-4E1D-9A61-26CA379F29A7}',{$ENDIF}GDBPointer(pprojpoint),sizeof(GDBLineProj));
324 
325   ProjectProc(CoordInWCS.lbegin,tv);
326   pprojpoint^[0]:=pGDBvertex2D(@tv)^;
327   ProjectProc(CoordInWCS.lEnd,tv);
328   pprojpoint^[1]:=pGDBvertex2D(@tv)^;
329   ProjectProc(Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 4),tv);
330   pprojpoint^[2]:=pGDBvertex2D(@tv)^;
331   ProjectProc(Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 3),tv);
332   pprojpoint^[3]:=pGDBvertex2D(@tv)^;
333   ProjectProc(Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 2),tv);
334   pprojpoint^[4]:=pGDBvertex2D(@tv)^;
335   ProjectProc(Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 2 / 3),tv);
336   pprojpoint^[5]:=pGDBvertex2D(@tv)^;
337   ProjectProc(Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 3 / 4),tv);
338   pprojpoint^[6]:=pGDBvertex2D(@tv)^;
339 
340   {ptv:=@CoordInWCS.lbegin;
341   ptv2d:=@pprojpoint^[0];
342   for i:=0 to 6 do
343   begin                   iuy
344   myGluProject(ptv^.x,ptv^.y,ptv^.z,@gdb.GetCurrentDWG.pcamera^.modelMatrix,@gdb.GetCurrentDWG.pcamera^.projMatrix,@gdb.GetCurrentDWG.pcamera^.viewport,ptv2d.x,ptv2d.y,tv.z);
345   inc(ptv);
346   inc(ptv2d);
347   end;}
348   //pdx:=PProjPoint[1].x-PProjPoint[0].x;
349   //pdy:=PProjPoint[1].y-PProjPoint[0].y;
350   inherited;
351 
352 end;
GDBObjLine.getsnapnull353 function GDBObjLine.getsnap;
354 var t,d,e:GDBDouble;
355     tv,n,v,dir:gdbvertex;
356 begin
357      if onlygetsnapcount=9 then
358      begin
359           result:=false;
360           exit;
361      end;
362      result:=true;
363      dir:=VertexSub(CoordInWCS.lEnd,CoordInWCS.lBegin);
364      case onlygetsnapcount of
365      0:begin
366             if (SnapMode and osm_endpoint)<>0
367             then
368             begin
369             osp.worldcoord:=CoordInWCS.lend;
370             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[1];
371             osp.ostype:=os_end;
372             end
373             else osp.ostype:=os_none;
374        end;
375      1:begin
376             if (SnapMode and osm_4)<>0
377             then
378             begin
379             osp.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 4);
380             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[2];
381             osp.ostype:=os_1_4;
382             end
383             else osp.ostype:=os_none;
384        end;
385      2:begin
386             if (SnapMode and osm_3)<>0
387             then
388             begin
389             osp.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 3);
390             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[3];
391             osp.ostype:=os_1_3;
392             end
393             else osp.ostype:=os_none;
394        end;
395      3:begin
396             if (SnapMode and osm_midpoint)<>0
397             then
398             begin
399             osp.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 2);
400             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[4];
401             osp.ostype:=os_midle;
402             end
403             else osp.ostype:=os_none;
404        end;
405      4:begin
406             if (SnapMode and osm_3)<>0
407             then
408             begin
409             osp.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 2 / 3);
410             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[5];
411             osp.ostype:=os_2_3;
412             end
413             else osp.ostype:=os_none;
414        end;
415      5:begin
416             if (SnapMode and osm_4)<>0
417             then
418             begin
419             osp.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 3 / 4);
420             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[6];
421             osp.ostype:=os_3_4;
422             end
423             else osp.ostype:=os_none;
424        end;
425      6:begin
426             if (SnapMode and osm_endpoint)<>0
427             then
428             begin
429             osp.worldcoord:=CoordInWCS.lbegin;
430             pgdbvertex2d(@osp.dispcoord)^:=pprojpoint^[0];
431             osp.ostype:=os_begin;
432             end
433             else osp.ostype:=os_none;
434        end;
435      7:begin
436             if (SnapMode and osm_perpendicular)<>0
437             then
438             begin
439             tv:=vectordot(dir,{GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.dir);
440             t:= -((CoordInWCS.lbegin.x-{GDB.GetCurrentDWG.OGLwindow1.}param.lastpoint.x)*dir.x+(CoordInWCS.lbegin.y-{GDB.GetCurrentDWG.OGLwindow1.}param.lastpoint.y)*dir.y+(CoordInWCS.lbegin.z-{GDB.GetCurrentDWG.OGLwindow1.}param.lastpoint.z)*dir.z)/
441                  ({sqr(dir.x)+sqr(dir.y)+sqr(dir.z)}SqrVertexlength(self.CoordInWCS.lBegin,self.CoordInWCS.lEnd){length_2});
442             if (t>=0) and (t<=1)
443             then
444             begin
445             osp.worldcoord.x:=CoordInWCS.lbegin.x+t*dir.x;
446             osp.worldcoord.y:=CoordInWCS.lbegin.y+t*dir.y;
447             osp.worldcoord.z:=CoordInWCS.lbegin.z+t*dir.z;
448             {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(osp.worldcoord,tv);
449             osp.dispcoord:=tv;
450             osp.ostype:=os_perpendicular;
451             end
452             else osp.ostype:=os_none;
453             end
454             else osp.ostype:=os_none;
455        end;
456      8:begin
457             if (SnapMode and osm_nearest)<>0
458             then
459             begin
460             tv:=vectordot(dir,{GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.dir);
461             n:=vectordot({GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.dir,tv);
462             n:=NormalizeVertex(n);
463             v.x:={GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.lbegin.x-CoordInWCS.lbegin.x;
464             v.y:={GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.lbegin.y-CoordInWCS.lbegin.y;
465             v.z:={GDB.GetCurrentDWG.OGLwindow1.}param.md.mouseray.lbegin.z-CoordInWCS.lbegin.z;
466             d:=scalardot(n,v);
467             e:=scalardot(n,dir);
468             if e<eps then osp.ostype:=os_none
469                      else
470                          begin
471                               if d<eps then osp.ostype:=os_none
472                                        else
473                                            begin
474                                                 t:=d/e;
475                                                 if (t>1)or(t<0)then osp.ostype:=os_none
476                                                 else
477                                                 begin
478             osp.worldcoord.x:=CoordInWCS.lbegin.x+t*dir.x;
479             osp.worldcoord.y:=CoordInWCS.lbegin.y+t*dir.y;
480             osp.worldcoord.z:=CoordInWCS.lbegin.z+t*dir.z;
481             {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(osp.worldcoord,tv);
482             osp.dispcoord:=tv;
483             osp.ostype:=os_nearest;
484                                                end;
485                                            end;
486 
487                          end;
488             end
489             else osp.ostype:=os_none;
490        end;
491      end;
492      inc(onlygetsnapcount);
493 end;
line2dintercepnull494 function line2dintercep(var x11, y11, x12, y12, x21, y21, x22, y22: GDBDouble; out t1,t2: GDBDouble): GDBBoolean;
495 var
496   d, d1, d2, dx1,dy1,dx2,dy2: GDBDouble;
497 begin
498   t1 := 0;
499   t2 := 0;
500   result := false;
501   dy1:=(y12 - y11);
502   dx2:=(x21 - x22);
503   dy2:=(y21 - y22);
504   dx1:=(x12 - x11);
505   D := dy1{(y12 - y11)} * dx2{(x21 - x22)} - dy2{(y21 - y22)} * dx1{(x12 - x11)};
506   if {(D <> 0)}abs(d)>{bigeps}sqreps then
507   begin
508        D1 := (y12 - y11) * (x21 - x11) - (y21 - y11) * (x12 - x11);
509        D2 := (y21 - y11) * (x21 - x22) - (y21 - y22) * (x21 - x11);
510     t2 := D1 / D;
511     t1 := D2 / D;
512     if ((t1 <= 1) and (t1 >= 0) and (t2 >= 0) and (t2 <= 1)) then
513     begin
514       result := true;
515     end;
516   end;
517 end;
GDBObjLine.getintersectnull518 function GDBObjLine.getintersect;
519 var t1,t2,dist:GDBDouble;
520     tv1,tv2,dir,dir2{,e}:gdbvertex;
521 begin
522      if (onlygetsnapcount=1)or(pobj^.{vp.id}getobjtype<>gdblineid) then
523      begin
524           result:=false;
525           exit;
526      end;
527      result:=true;
528      case onlygetsnapcount of
529      0:begin
530             if ((SnapMode and osm_apparentintersection)<>0)or((SnapMode and osm_intersection)<>0)
531             then
532             begin
533             if not assigned(pgdbobjline(pobj)^.pprojpoint) then
534                                                                begin
535                                                                //pgdbobjline(pobj)^.RenderFeedback(gdb.GetCurrentDWG.pcamera^.POSCOUNT,gdb.GetCurrentDWG.pcamera^,nil);
536                                                                debugln('{E}pobj)^.pprojpoint=nil;//(((((((');
537                                                                osp.ostype:=os_none;
538                                                                exit;
539                                                                end;
540             if line2dintercep(pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y,   pgdbobjline(pobj)^.pprojpoint[0].x,pgdbobjline(pobj)^.pprojpoint[0].y,pgdbobjline(pobj)^.pprojpoint[1].x,pgdbobjline(pobj)^.pprojpoint[1].y,  t1,t2)
541             then
542                 begin
543                      dir:=VertexSub(CoordInWCS.lEnd,CoordInWCS.lBegin);
544                      dir2:=VertexSub(pgdbobjline(pobj)^.CoordInWCS.lEnd,pgdbobjline(pobj)^.CoordInWCS.lBegin);
545                      tv1.x:=CoordInWCS.lbegin.x+dir.x*t1;
546                      tv1.y:=CoordInWCS.lbegin.y+dir.y*t1;
547                      tv1.z:=CoordInWCS.lbegin.z+dir.z*t1;
548                      tv2.x:=pgdbobjline(pobj)^.CoordInWCS.lbegin.x+dir2.x*t2;
549                      tv2.y:=pgdbobjline(pobj)^.CoordInWCS.lbegin.y+dir2.y*t2;
550                      tv2.z:=pgdbobjline(pobj)^.CoordInWCS.lbegin.z+dir2.z*t2;
551                      dist:=Vertexlength(tv1,tv2);
552                      if dist<bigeps
553                      then
554                          begin
555                               if (SnapMode and osm_intersection)<>0
556                               then
557                               begin
558                               osp.worldcoord:=tv1;
559                               {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(osp.worldcoord,osp.dispcoord);
560                               osp.ostype:=os_intersection;
561                               end
562                               else osp.ostype:=os_none;
563                          end
564                      else
565                          begin
566                               if (SnapMode and osm_apparentintersection)<>0
567                               then
568                               begin
569                               osp.worldcoord:=tv1;
570                               line2dintercep(pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y,   pgdbobjline(pobj)^.pprojpoint[0].x,pgdbobjline(pobj)^.pprojpoint[0].y,pgdbobjline(pobj)^.pprojpoint[1].x,pgdbobjline(pobj)^.pprojpoint[1].y,  t1,t2);
571                               {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(osp.worldcoord,osp.dispcoord);
572                               osp.ostype:=os_apparentintersection;
573                               end
574                               else osp.ostype:=os_none;
575                          end;
576                 end;
577             end
578             else osp.ostype:=os_none;
579        end;
580      end;
581      inc(onlygetsnapcount);
582 end;
GDBObjLine.Clonenull583 function GDBObjLine.Clone;
584 var tvo: PGDBObjLine;
585 begin
586   GDBGetMem({$IFDEF DEBUGBUILD}'{5A1B005F-39F1-431B-B65E-0C532AEFA5D0}-GDBObjLine.Clone',{$ENDIF}GDBPointer(tvo), sizeof(GDBObjLine));
587   tvo^.init(bp.ListPos.owner,vp.Layer, vp.LineWeight, CoordInOCS.lBegin, CoordInOCS.lEnd);
588   CopyVPto(tvo^);
589   tvo^.CoordInOCS.lBegin.y := tvo^.CoordInOCS.lBegin.y;
590   tvo^.bp.ListPos.Owner:=own;
591   //tvo^.format;
592   result := tvo;
593 end;
594 procedure GDBObjLine.SaveToDXF;
595 begin
596   SaveToDXFObjPrefix(outhandle,'LINE','AcDbLine',IODXFContext);
597   dxfvertexout(outhandle,10,CoordInOCS.lbegin);
598   dxfvertexout(outhandle,11,CoordInOCS.lend);
599 end;
600 procedure GDBObjLine.rtedit;
601 begin
602   if mode = os_midle then
603   begin
604     CoordInOCS.lbegin := VertexAdd(pgdbobjline(refp)^.CoordInOCS.lBegin, dist);
605     CoordInOCS.lend := VertexAdd(pgdbobjline(refp)^.CoordInOCS.lend, dist);
606   end
607   else if mode = os_end then
608   begin
609     CoordInOCS.lend := VertexAdd(pgdbobjline(refp)^.CoordInOCS.lend, dist);
610   end
611   else if mode = os_begin then
612   begin
613     CoordInOCS.lbegin := VertexAdd(pgdbobjline(refp)^.CoordInOCS.lBegin, dist);
614   end;
615   //format;
616 end;
617 
618 procedure GDBObjLine.rtsave;
619 begin
620   pgdbobjline(refp)^.CoordInOCS.lBegin := CoordInOCS.lbegin;
621   pgdbobjline(refp)^.CoordInOCS.lEnd := CoordInOCS.lend;
622   //pgdbobjline(refp)^.format;
623 end;
624 procedure GDBObjLine.TransformAt;
625 begin
626   CoordInOCS.lbegin:=uzegeometry.VectorTransform3D(pgdbobjline(p)^.CoordInOCS.lBegin,t_matrix^);
627   CoordInOCS.lend:=VectorTransform3D(pgdbobjline(p)^.CoordInOCS.lend,t_matrix^);
628 end;
GDBObjLine.beforertmodifynull629 function GDBObjLine.beforertmodify;
630 begin
631      GDBGetMem({$IFDEF DEBUGBUILD}'{D2E91E60-41CC-45FE-AC5E-CAEC5013C0ED}',{$ENDIF}result,sizeof(tlinertmodify));
632      clearrtmodify(result);
633 end;
634 procedure GDBObjLine.clearrtmodify(p:GDBPointer);
635 begin
636      fillchar(p^,sizeof(tlinertmodify),0);
637 end;
GDBObjLine.IsRTNeedModifynull638 function GDBObjLine.IsRTNeedModify(const Point:PControlPointDesc; p:GDBPointer):Boolean;
639 begin
640      result:=false;
641   case point.pointtype of
642        os_begin:begin
643                      if not ptlinertmodify(p)^.lbegin then
644                                                                result:=true;
645                      ptlinertmodify(p)^.lbegin:=true;
646                 end;
647        os_end:begin
648                      if not ptlinertmodify(p)^.lend then
649                                                              result:=true;
650                      ptlinertmodify(p)^.lend:=true;
651                 end;
652        os_midle:begin
653                      if (not ptlinertmodify(p)^.lbegin)
654                      and (not ptlinertmodify(p)^.lend) then
655                                                                result:=true;
656                      ptlinertmodify(p)^.lbegin:=true;
657                      ptlinertmodify(p)^.lend:=true;
658                 end;
659   end;
660 
661 end;
662 
663 procedure GDBObjLine.rtmodifyonepoint(const rtmod:TRTModifyData);
664 var
665     tv,tv2:GDBVERTEX;
666 begin
667           case rtmod.point.pointtype of
668                os_begin:begin
669                              CoordInOCS.lbegin:=VertexAdd(rtmod.point.worldcoord, rtmod.dist);
670                         end;
671                os_end:begin
672                            CoordInOCS.lend:=VertexAdd(rtmod.point.worldcoord, rtmod.dist);
673                       end;
674                os_midle:begin
675                              tv:=uzegeometry.VertexSub(CoordInOCS.lend,CoordInOCS.lbegin);
676                              tv:=uzegeometry.VertexMulOnSc(tv,0.5);
677                              tv2:=VertexAdd(rtmod.point.worldcoord, rtmod.dist);
678                              CoordInOCS.lbegin:=VertexSub(tv2, tv);
679                              CoordInOCS.lend:=VertexAdd(tv2,tv);
680                         end;
681           end;
682 
683 end;
684 procedure GDBObjLine.remaponecontrolpoint(pdesc:pcontrolpointdesc);
685 begin
686                     case pdesc^.pointtype of
687                     os_begin:begin
688                                   pdesc.worldcoord:=CoordInWCS.lbegin;
689                                   pdesc.dispcoord.x:=round(PProjPoint[0].x);
690                                   pdesc.dispcoord.y:=round(PProjPoint[0].y);
691                              end;
692                     os_end:begin
693                                 pdesc.worldcoord:=CoordInWCS.lend;
694                                 pdesc.dispcoord.x:=round(PProjPoint[1].x);
695                                 pdesc.dispcoord.y:=round(PProjPoint[1].y);
696                              end;
697                     os_midle:begin
698                                   pdesc.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 2);
699                                   pdesc.dispcoord.x:=round(PProjPoint[4].x);
700                                   pdesc.dispcoord.y:=round(PProjPoint[4].y);
701                              end;
702                     end;
703 end;
704 procedure GDBObjLine.addcontrolpoints(tdesc:GDBPointer);
705 var pdesc:controlpointdesc;
706 begin
707           PSelectedObjDesc(tdesc)^.pcontrolpoint^.init({$IFDEF DEBUGBUILD}'{4CBC9A73-A88D-443B-B925-2F0611D82AB0}',{$ENDIF}3);
708 
709           pdesc.selected:=false;
710           pdesc.pobject:=nil;
711 
712           //renderfeedback(gdb.GetCurrentDWG.pcamera^.POSCOUNT,gdb.GetCurrentDWG.pcamera^,nil);
713 
714           pdesc.pointtype:=os_midle;
715           pdesc.attr:=[];
716           pdesc.worldcoord:=Vertexmorph(CoordInWCS.lbegin, CoordInWCS.lend, 1 / 2);
717           {pdesc.dispcoord.x:=round(PProjPoint[4].x);
718           pdesc.dispcoord.y:=round(PProjPoint[4].y);}
719           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
720 
721           pdesc.pointtype:=os_begin;
722           pdesc.attr:=[CPA_Strech];
723           pdesc.worldcoord:=CoordInWCS.lbegin;
724           {pdesc.dispcoord.x:=round(PProjPoint[0].x);
725           pdesc.dispcoord.y:=round(PProjPoint[0].y);}
726           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
727 
728           pdesc.pointtype:=os_end;
729           pdesc.attr:=[CPA_Strech];
730           pdesc.worldcoord:=CoordInWCS.lend;
731           {pdesc.dispcoord.x:=round(PProjPoint[1].x);
732           pdesc.dispcoord.y:=round(PProjPoint[1].y);}
733           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
734 end;
735 {function GDBObjLine.InRect;
736 begin
737      result:=IREmpty;
738      if pprojpoint=nil then
739                            exit;
740      if pointinquad2d(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, pprojpoint[0].x,pprojpoint[0].y)
741     and pointinquad2d(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, pprojpoint[1].x,pprojpoint[1].y)
742       then
743           begin
744                result:=IRFully;
745           end
746       else
747           if
748           intercept2d2(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y)
749        or intercept2d2(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y)
750        or intercept2d2(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y)
751        or intercept2d2(GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame2.y, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.x, GDB.GetCurrentDWG.OGLwindow1.param.seldesc.Frame1.y, pprojpoint[0].x,pprojpoint[0].y,pprojpoint[1].x,pprojpoint[1].y)
752           then
753           begin
754                result:=IRPartially;
755           end
756 end;}
757 
758 procedure GDBObjLine.transform;
759 var tv:GDBVertex4D;
760 begin
761   pgdbvertex(@tv)^:=CoordInOCS.lbegin;
762   tv.w:=1;
763   tv:=vectortransform(tv,t_matrix);
764   CoordInOCS.lbegin:=pgdbvertex(@tv)^;
765 
766   pgdbvertex(@tv)^:=CoordInOCS.lend;
767   tv.w:=1;
768   tv:=vectortransform(tv,t_matrix);
769   CoordInOCS.lend:=pgdbvertex(@tv)^;
770 end;
AllocLinenull771 function AllocLine:PGDBObjLine;
772 begin
773   GDBGetMem({$IFDEF DEBUGBUILD}'{AllocLine}',{$ENDIF}pointer(result),sizeof(GDBObjLine));
774 end;
AllocAndInitLinenull775 function AllocAndInitLine(owner:PGDBObjGenericWithSubordinated):PGDBObjLine;
776 begin
777   result:=AllocLine;
778   result.initnul(owner);
779   result.bp.ListPos.Owner:=owner;
780 end;
781 procedure SetLineGeomProps(Pline:PGDBObjLine;args:array of const);
782 var
783    counter:integer;
784 begin
785   counter:=low(args);
786   Pline.CoordInOCS.lBegin:=CreateVertexFromArray(counter,args);
787   Pline.CoordInOCS.lEnd:=CreateVertexFromArray(counter,args);
788 end;
AllocAndCreateLinenull789 function AllocAndCreateLine(owner:PGDBObjGenericWithSubordinated;args:array of const):PGDBObjLine;
790 begin
791   result:=AllocAndInitLine(owner);
792   //owner^.AddMi(@result);
793   SetLineGeomProps(result,args);
794 end;
GDBObjLine.CreateInstancenull795 class function GDBObjLine.CreateInstance:PGDBObjLine;
796 begin
797   result:=AllocAndInitLine(nil);
798 end;
799 begin
800   RegisterDXFEntity(GDBlineID,'LINE','Line',@AllocLine,@AllocAndInitLine,@SetLineGeomProps,@AllocAndCreateLine);
801 end.
802