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 unit uzeentellipse;
19 {$INCLUDE def.inc}
20 interface
21 uses
22     uzeentityfactory,uzeentsubordinated,uzgldrawcontext,uzedrawingdef,uzecamera,
23     uzeentwithlocalcs,gzctnrvectorpobjects,uzestyleslayers,uzbtypesbase,
24     UGDBSelectedObjArray,uzeentity,UGDBOutbound2DIArray,UGDBPoint3DArray,
25     uzbgeomtypes,UGDBOpenArrayOfByte,varman,varmandef,uzbtypes,uzeconsts,
26     uzglviewareadata,uzegeometry,uzeffdxfsupport,uzbmemman,uzeentplain;
27 type
28 {REGISTEROBJECTTYPE GDBObjEllipse}
29 {Export+}
30   ptEllipsertmodify=^tEllipsertmodify;
31   tEllipsertmodify=packed record
32                         p1,p2,p3:GDBVertex2d;
33                   end;
34 PGDBObjEllipse=^GDBObjEllipse;
35 GDBObjEllipse={$IFNDEF DELPHI}packed{$ENDIF} object(GDBObjPlain)
36                  RR:GDBDouble;(*saved_to_shd*)
37                  MajorAxis:GDBvertex;
38                  Ratio:GDBDouble;(*saved_to_shd*)
39                  StartAngle:GDBDouble;(*saved_to_shd*)
40                  EndAngle:GDBDouble;(*saved_to_shd*)
41                  angle:GDBDouble;
42                  Vertex3D_in_WCS_Array:GDBPoint3DArray;
43                  length:GDBDouble;
44                  q0,q1,q2:GDBvertex;
45                  pq0,pq1,pq2:GDBvertex;
46                  constructor init(own:GDBPointer;layeraddres:PGDBLayerProp;LW:GDBSmallint;p:GDBvertex;{RR,}S,E:GDBDouble;majaxis:GDBVertex);
47                  constructor initnul;
48                  procedure LoadFromDXF(var f:GDBOpenArrayOfByte;ptu:PExtensionData;var drawing:TDrawingDef);virtual;
49 
50                  procedure SaveToDXF(var outhandle:{GDBInteger}GDBOpenArrayOfByte;var drawing:TDrawingDef;var IODXFContext:TIODXFContext);virtual;
51                  procedure DrawGeometry(lw:GDBInteger;var DC:TDrawContext{infrustumactualy:TActulity;subrender:GDBInteger});virtual;
52                  procedure addcontrolpoints(tdesc:GDBPointer);virtual;
53                  procedure remaponecontrolpoint(pdesc:pcontrolpointdesc);virtual;
54                  procedure CalcObjMatrix;virtual;
55                  procedure FormatEntity(var drawing:TDrawingDef;var DC:TDrawContext);virtual;
56                  procedure createpoint;virtual;
57                  procedure getoutbound(var DC:TDrawContext);virtual;
58                  procedure RenderFeedback(pcount:TActulity;var camera:GDBObjCamera; ProjectProc:GDBProjectProc;var DC:TDrawContext);virtual;
59                  procedure projectpoint;virtual;
onmousenull60                  function onmouse(var popa:TZctnrVectorPGDBaseObjects;const MF:ClipArray;InSubEntry:GDBBoolean):GDBBoolean;virtual;
getsnapnull61                  function getsnap(var osp:os_record; var pdata:GDBPointer; const param:OGLWndtype; ProjectProc:GDBProjectProc;SnapMode:TGDBOSMode):GDBBoolean;virtual;
beforertmodifynull62                  function beforertmodify:GDBPointer;virtual;
63                  procedure rtmodifyonepoint(const rtmod:TRTModifyData);virtual;
IsRTNeedModifynull64                  function IsRTNeedModify(const Point:PControlPointDesc; p:GDBPointer):Boolean;virtual;
Clonenull65                  function Clone(own:GDBPointer):PGDBObjEntity;virtual;
66                  procedure rtsave(refp:GDBPointer);virtual;
67                  destructor done;virtual;
GetObjTypeNamenull68                  function GetObjTypeName:GDBString;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;
CalcObjMatrixWithoutOwnernull71                  function CalcObjMatrixWithoutOwner:DMatrix4D;virtual;
72                  procedure transform(const t_matrix:DMatrix4D);virtual;
73                  procedure TransformAt(p:PGDBObjEntity;t_matrix:PDMatrix4D);virtual;
74                  procedure ReCalcFromObjMatrix;virtual;
75 
CreateInstancenull76                  function CreateInstance:PGDBObjEllipse;static;
GetObjTypenull77                  function GetObjType:TObjID;virtual;
78            end;
79 {EXPORT-}
80 implementation
81 //uses log;
82 procedure GDBObjEllipse.TransformAt;
83 var
84     tv:GDBVertex4D;
85 begin
86     objmatrix:=uzegeometry.MatrixMultiply(PGDBObjWithLocalCS(p)^.objmatrix,t_matrix^);
87 
88     tv:=PGDBVertex4D(@t_matrix[3])^;
89     PGDBVertex4D(@t_matrix[3])^:=NulVertex4D;
90     MajorAxis:=VectorTransform3D(PGDBObjEllipse(p)^.MajorAxis,t_matrix^);
91     PGDBVertex4D(@t_matrix[3])^:=tv;
92 
93      {Local.oz:=PGDBVertex(@objmatrix[2])^;
94 
95      Local.p_insert:=PGDBVertex(@objmatrix[3])^;}ReCalcFromObjMatrix;
96 end;
97 procedure GDBObjEllipse.transform;
98 var {tv,}tv2:GDBVertex4D;
99 begin
100   inherited;
101 
102   tv2:=PGDBVertex4D(@t_matrix[3])^;
103   PGDBVertex4D(@t_matrix[3])^:=NulVertex4D;
104   MajorAxis:=VectorTransform3D(MajorAxis,t_matrix);
105   PGDBVertex4D(@t_matrix[3])^:=tv2;
106 
107   ReCalcFromObjMatrix;
108 end;
109 procedure GDBObjEllipse.ReCalcFromObjMatrix;
110 //var
111     //ox:gdbvertex;
112 begin
113      inherited;
114      {Local.basis.ox:=PGDBVertex(@objmatrix[0])^;
115      Local.basis.oy:=PGDBVertex(@objmatrix[1])^;
116 
117      Local.basis.ox:=normalizevertex(Local.basis.ox);
118      Local.basis.oy:=normalizevertex(Local.basis.oy);
119      Local.basis.oz:=normalizevertex(Local.basis.oz);}
120 
121      Local.P_insert:=PGDBVertex(@objmatrix[3])^;
122 
123 
124      //scale.x:=uzegeometry.oneVertexlength(PGDBVertex(@objmatrix[0])^);
125      //scale.y:=uzegeometry.oneVertexlength(PGDBVertex(@objmatrix[1])^);
126      //scale.z:=uzegeometry.oneVertexlength(PGDBVertex(@objmatrix[2])^);
127 
128      {if (abs (Local.basis.oz.x) < 1/64) and (abs (Local.basis.oz.y) < 1/64) then
129                                                                     ox:=CrossVertex(YWCS,Local.basis.oz)
130                                                                 else
131                                                                     ox:=CrossVertex(ZWCS,Local.basis.oz);}
132      //normalizevertex(ox);
133      //rotate:=uzegeometry.scalardot(Local.basis.ox,ox);
134     // rotate:=arccos(rotate)*180/pi;
135      //if local.basis.OX.y<-eps then rotate:=360-rotate;
136 end;
137 
GDBObjEllipse.CalcObjMatrixWithoutOwnernull138 function GDBObjEllipse.CalcObjMatrixWithoutOwner;
139 var rotmatr,dispmatr{,m1}:DMatrix4D;
140 begin
141      //Local.oz:=NormalizeVertex(Local.oz);
142      Local.basis.ox:=MajorAxis;
143      Local.basis.oy:=CrossVertex(Local.basis.oz,Local.basis.ox);
144 
145      Local.basis.ox:=NormalizeVertex(Local.basis.ox);
146      Local.basis.oy:=NormalizeVertex(Local.basis.oy);
147      Local.basis.oz:=NormalizeVertex(Local.basis.oz);
148 
149      rotmatr:=onematrix;
150      PGDBVertex(@rotmatr[0])^:=Local.basis.ox;
151      PGDBVertex(@rotmatr[1])^:=Local.basis.oy;
152      PGDBVertex(@rotmatr[2])^:=Local.basis.oz;
153 
154      dispmatr:=onematrix;
155      PGDBVertex(@dispmatr[3])^:=Local.p_insert;
156 
157      result:=MatrixMultiply({dispmatr,}rotmatr,dispmatr);
158 end;
GDBObjEllipse.CalcTrueInFrustumnull159 function GDBObjEllipse.CalcTrueInFrustum;
160 var i{,count}:GDBInteger;
161     //d1,d2,d3,d4:gdbdouble;
162 begin
163       for i:=0 to 5 do
164       begin
165       if(frustum[i][0] * P_insert_in_WCS.x + frustum[i][1] * P_insert_in_WCS.y + frustum[i][2] * P_insert_in_WCS.z + frustum[i][3]+rr < 0 )
166       then
167       begin
168            result:=IREmpty;
169            exit;
170            //system.break;
171       end;
172       end;
173       result:=Vertex3D_in_WCS_Array.CalcTrueInFrustum(frustum);
174 end;
GDBObjEllipse.calcinfrustumnull175 function GDBObjEllipse.calcinfrustum;
176 var i:GDBInteger;
177 begin
178       result:=true;
179       for i:=0 to 4 do
180       begin
181       if(frustum[i][0] * outbound[0].x + frustum[i][1] * outbound[0].y + frustum[i][2] * outbound[0].z + frustum[i][3] < 0 )
182       and(frustum[i][0] * outbound[1].x + frustum[i][1] * outbound[1].y + frustum[i][2] * outbound[1].z + frustum[i][3] < 0 )
183       and(frustum[i][0] * outbound[2].x + frustum[i][1] * outbound[2].y + frustum[i][2] * outbound[2].z + frustum[i][3] < 0 )
184       and(frustum[i][0] * outbound[3].x + frustum[i][1] * outbound[3].y + frustum[i][2] * outbound[3].z + frustum[i][3] < 0 )
185       then
186       begin
187            result:=false;
188            system.break;
189       end;
190       end;
191 end;
GDBObjEllipse.GetObjTypeNamenull192 function GDBObjEllipse.GetObjTypeName;
193 begin
194      result:=ObjN_GDBObjEllipse;
195 end;
196 destructor GDBObjEllipse.done;
197 begin
198      inherited done;
199      //Vertex3D_in_WCS_Array.Clear;
200      Vertex3D_in_WCS_Array.Done;
201 end;
202 constructor GDBObjEllipse.initnul;
203 begin
204   startangle := 0;
205   endangle := 2*pi;
206   PProjoutbound:=nil;
207   majoraxis:=onevertex;
208   inherited initnul(nil);
209   //vp.ID:=GDBEllipseID;
210   //r := 1;
211   Vertex3D_in_WCS_Array.init({$IFDEF DEBUGBUILD}'{B591E6C2-9BD5-4099-BE5A-5CB3911661B7}',{$ENDIF}100);
212 end;
213 constructor GDBObjEllipse.init;
214 begin
215   inherited init(own,layeraddres, lw);
216   //vp.ID:=GDBEllipseID;
217   Local.p_insert := p;
218   //r := rr;
219   startangle := s;
220   endangle := e;
221   majoraxis:=majaxis;
222   PProjoutbound:=nil;
223   Vertex3D_in_WCS_Array.init({$IFDEF DEBUGBUILD}'{AEF4273C-4EE8-4520-B23A-04C3AD6DABE3}',{$ENDIF}100);
224   //format;
225 end;
GDBObjEllipse.GetObjTypenull226 function GDBObjEllipse.GetObjType;
227 begin
228      result:=GDBEllipseID;
229 end;
230 procedure GDBObjEllipse.CalcObjMatrix;
231 var m1:DMatrix4D;
232     v:GDBvertex4D;
233 begin
234   inherited CalcObjMatrix;
235   m1:=ONEMATRIX;
236   m1[0, 0] := {ratio*}onevertexlength(majoraxis);
237   m1[1, 1] := ratio*onevertexlength(majoraxis);
238   m1[2, 2] := {ratio*onevertexlength(majoraxis)}1;
239   objmatrix:=matrixmultiply(m1,objmatrix);
240 
241     pgdbvertex(@v)^:=local.p_insert;
242   v.z:=0;
243   v.w:=1;
244   m1:=objMatrix;
245   MatrixInvert(m1);
246   v:=VectorTransform(v,m1);
247 end;
248 procedure GDBObjEllipse.FormatEntity(var drawing:TDrawingDef;var DC:TDrawContext);
249 var
250   v:GDBvertex4D;
251 begin
252   if self.Ratio<=1 then
253                       rr:=uzegeometry.oneVertexlength(majoraxis)
254                    else
255                       rr:=uzegeometry.oneVertexlength(majoraxis)*ratio;
256 
257   calcObjMatrix;
258   angle := endangle - startangle;
259   if angle < 0 then angle := 2 * pi + angle;
260   length := abs(angle){*pi/180} * rr;//---------------------------------------------------------------
261   v.x:=cos(startangle{*pi/180});
262   v.y:=sin(startangle{*pi/180});
263   v.z:=0;
264   v.w:=1;
265   v:=VectorTransform(v,objMatrix);
266   q0:=pgdbvertex(@v)^;
267   v.x:=cos(startangle+angle{*pi/180}/2);
268   v.y:=sin(startangle+angle{*pi/180}/2);
269   v.z:=0;
270   v.w:=1;
271   v:=VectorTransform(v,objMatrix);
272   q1:=pgdbvertex(@v)^;
273   v.x:=cos(endangle{*pi/180});
274   v.y:=sin(endangle{*pi/180});
275   v.z:=0;
276   v.w:=1;
277   v:=VectorTransform(v,objMatrix);
278   q2:=pgdbvertex(@v)^;
279 
280   calcbb(dc);
281   createpoint;
282 end;
283 procedure GDBObjEllipse.getoutbound;
284 var //tv,tv2:GDBVertex;
285     t,b,l,rrr,n,f:GDBDouble;
286     i:integer;
287 begin
288   outbound[0]:=VectorTransform3d(CreateVertex(-1,1,0),objMatrix);
289   outbound[1]:=VectorTransform3d(CreateVertex(1,1,0),objMatrix);
290   outbound[2]:=VectorTransform3d(CreateVertex(1,-1,0),objMatrix);
291   outbound[3]:=VectorTransform3d(CreateVertex(-1,-1,0),objMatrix);
292 
293   {outbound[0]:=VectorTransform3d(CreateVertex(cos(startangle),sin(startangle),0),objMatrix);
294   outbound[1]:=VectorTransform3d(CreateVertex(cos(endangle),sin(endangle),0),objMatrix);
295   tv:=vertexsub(pgdbvertex(@outbound[1])^,pgdbvertex(@outbound[0])^);
296   t:=tv.x;
297   tv.x:=tv.y;
298   tv.y:=t;
299   outbound[2]:=vertexadd(outbound[1],tv);
300   outbound[3]:=vertexadd(outbound[0],tv);}
301 
302 
303   l:=outbound[0].x;
304   rrr:=outbound[0].x;
305   t:=outbound[0].y;
306   b:=outbound[0].y;
307   n:=outbound[0].z;
308   f:=outbound[0].z;
309   for i:=1 to 3 do
310   begin
311   if outbound[i].x<l then
312                          l:=outbound[i].x;
313   if outbound[i].x>rrr then
314                          rrr:=outbound[i].x;
315   if outbound[i].y<b then
316                          b:=outbound[i].y;
317   if outbound[i].y>t then
318                          t:=outbound[i].y;
319   if outbound[i].z<n then
320                          n:=outbound[i].z;
321   if outbound[i].z>f then
322                          f:=outbound[i].z;
323   end;
324 
325   vp.BoundingBox.LBN:=CreateVertex(l,B,n);
326   vp.BoundingBox.RTF:=CreateVertex(rrr,T,f);
327   if PProjoutbound=nil then
328   begin
329        GDBGetMem({$IFDEF DEBUGBUILD}'{B9B13A5B-467C-4E8A-B4BD-6F54713EBC0D}',{$ENDIF}GDBPointer(PProjoutbound),sizeof(GDBOOutbound2DIArray));
330        PProjoutbound^.init({$IFDEF DEBUGBUILD}'{2D0D05D3-F10A-473F-88FC-D5FB9BD7B539}',{$ENDIF}4);
331   end;
332 end;
333 procedure GDBObjEllipse.createpoint;
334 var
335   //psymbol: PGDBByte;
336   i{, j, k}: GDBInteger;
337   //len: GDBWord;
338   //matr{,m1}: DMatrix4D;
339   v:GDBvertex;
340   pv:GDBVertex;
341 begin
342   {oglsm.myglpushmatrix;
343   glscaledf(r, r, 1);
344   gltranslatef(p_insert.x / r, p_insert.y / r, p_insert.z);
345   angle := endangle - startangle;
346   if angle < 0 then angle := 2 * pi + angle;
347   myglbegin(GL_line_strip);
348   glVertex3d(cos(startangle), sin(startangle), 0);
349   for i := 1 to arccount do
350   begin
351     glVertex3d(cos(startangle + i / arccount * angle), sin(startangle + i / arccount * angle), 0);
352   end;
353   myglend;
354   oglsm.myglpopmatrix;}
355   angle := endangle - startangle;
356   if angle < 0 then angle := 2 * pi + angle;
357 
358   Vertex3D_in_WCS_Array.clear;
359   {if ppoint<>nil then
360                      begin
361                           ppoint^.done;
362                           GDBFreeMem(ppoint);
363                      end;
364   GDBGetMem(PPoint,sizeof(GDBPoint2DArray));
365   PPoint^.init(lod+1);}
366   //matr:=objMatrix;
367   v.x:=cos(startangle);
368   v.y:=sin(startangle);
369   v.z:=0;
370   pv:=VectorTransform3D(v,objmatrix);
371   Vertex3D_in_WCS_Array.PushBackData(pv);
372 
373   lod:=100;  { TODO : А кто лод считать будет? }
374 
375   for i:=1 to lod do
376   begin
377               v.x:=cos(startangle+i / lod * angle);
378               v.y:=sin(startangle+i / lod * angle);
379               v.z:=0;
380               pv:=VectorTransform3D(v,objmatrix);
381               Vertex3D_in_WCS_Array.PushBackData(pv);
382   end;
383   Vertex3D_in_WCS_Array.Shrink;
384 end;
385 procedure GDBObjEllipse.Renderfeedback;
386 var //pm:DMatrix4D;
387     tv:GDBvertex;
388     d:GDBDouble;
389 begin
390            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(Local.p_insert,ProjP_insert);
391            pprojoutbound^.clear;
392            //pm:=gdb.GetCurrentDWG.pcamera^.modelMatrix;
393            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(outbound[0],tv);
394            pprojoutbound^.PushBackIfNotLastWithCompareProc(ToVertex2DI(tv),EqualVertex2DI);
395            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(outbound[1],tv);
396            pprojoutbound^.PushBackIfNotLastWithCompareProc(ToVertex2DI(tv),EqualVertex2DI);
397            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(outbound[2],tv);
398            pprojoutbound^.PushBackIfNotLastWithCompareProc(ToVertex2DI(tv),EqualVertex2DI);
399            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(outbound[3],tv);
400            pprojoutbound^.PushBackIfNotLastOrFirstWithCompareProc(ToVertex2DI(tv),EqualVertex2DI);
401            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(q0,pq0);
402            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(q1,pq1);
403            {gdb.GetCurrentDWG^.myGluProject2}ProjectProc(q2,pq2);
404            if pprojoutbound^.count<4 then
405            begin
406             lod:=4;
407             //projectpoint;
408            end
409            else
410            begin
411                 d:=pprojoutbound^.perimetr;
412                 d:=(angle/(2*pi))*(d/10);
413                 if d>255 then d:=255;
414                 if d<10 then d:=10;
415                 if lod<>round(d) then
416                 begin
417                      lod:=round(d);
418                      createpoint;
419                 end;
420                 projectpoint;
421            end;
422 end;
423 procedure GDBObjEllipse.DrawGeometry;
424 //var
425 //  i: GDBInteger;
426 begin
427 
428   DC.drawer.DrawClosedContour3DInModelSpace(Vertex3D_in_WCS_Array,DC.DrawingContext.matrixs);
429   //Vertex3D_in_WCS_Array.drawgeometry;
430 
431   inherited;
432 
433 end;
434 procedure GDBObjEllipse.projectpoint;
435 //var pm:DMatrix4D;
436 //    tv:GDBvertex;
437 //    tpv:GDBPolyVertex2D;
438 //    ptpv:PGDBPolyVertex2D;
439 //    i:GDBInteger;
440 begin
441 
442 end;
443 procedure GDBObjEllipse.SaveToDXF;
444 begin
445   SaveToDXFObjPrefix(outhandle,'ELLIPSE','AcDbEllipse',IODXFContext);
446   dxfvertexout(outhandle,10,Local.p_insert);
447   dxfvertexout(outhandle,11,majoraxis);
448     SaveToDXFObjPostfix(outhandle);
449 
450   //dxfGDBStringout(outhandle,100,'AcDbEllipse');
451   //WriteString_EOL(outhandle, '100');
452   //WriteString_EOL(outhandle, 'AcDbArc');
453   dxfGDBDoubleout(outhandle,40,ratio{ * 180 / pi});
454   dxfGDBDoubleout(outhandle,41,startangle{ * 180 / pi});
455   dxfGDBDoubleout(outhandle,42,endangle{ * 180 / pi});
456 end;
457 procedure GDBObjEllipse.LoadFromDXF;
458 var //s: GDBString;
459   byt{, code}: GDBInteger;
460 begin
461   //initnul;
462   byt:=readmystrtoint(f);
463   while byt <> 0 do
464   begin
465     if not LoadFromDXFObjShared(f,byt,ptu,drawing) then
466     if not dxfvertexload(f,10,byt,Local.P_insert) then
467     if not dxfvertexload(f,11,byt,MajorAxis) then
468     if not dxfGDBDoubleload(f,40,byt,ratio) then
469     if not dxfGDBDoubleload(f,41,byt,startangle) then
470     if not dxfGDBDoubleload(f,42,byt,endangle) then {s := }f.readgdbstring;
471     byt:=readmystrtoint(f);
472   end;
473   startangle := startangle{ * pi / 180};
474   endangle := endangle{ * pi / 180};
475   PProjoutbound:=nil;
476   //format;
477 end;
GDBObjEllipse.onmousenull478 function GDBObjEllipse.onmouse;
479 var i:GDBInteger;
480 begin
481      for i:=0 to 5 do
482      begin
483      if(mf[i][0] * P_insert_in_WCS.x + mf[i][1] * P_insert_in_WCS.y + mf[i][2] * P_insert_in_WCS.z + mf[i][3]+RR < 0 )
484      then
485      begin
486           result:=false;
487           //system.break;
488           exit;
489      end;
490      end;
491      result:=Vertex3D_in_WCS_Array.onmouse(mf,false);
492 end;
493 procedure GDBObjEllipse.remaponecontrolpoint(pdesc:pcontrolpointdesc);
494 begin
495                     case pdesc^.pointtype of
496                     os_begin:begin
497           pdesc.worldcoord:=q0;
498           pdesc.dispcoord.x:=round(Pq0.x);
499           pdesc.dispcoord.y:=round(Pq0.y);
500                              end;
501                     os_midle:begin
502           pdesc.worldcoord:=q1;
503           pdesc.dispcoord.x:=round(Pq1.x);
504           pdesc.dispcoord.y:=round(Pq1.y);
505                              end;
506                     os_end:begin
507           pdesc.worldcoord:=q2;
508           pdesc.dispcoord.x:=round(Pq2.x);
509           pdesc.dispcoord.y:=round(Pq2.y);
510                              end;
511                     end;
512 end;
513 procedure GDBObjEllipse.addcontrolpoints(tdesc:GDBPointer);
514 var pdesc:controlpointdesc;
515 begin
516           PSelectedObjDesc(tdesc)^.pcontrolpoint^.init({$IFDEF DEBUGBUILD}'{8E7285C9-05AD-4D34-9E9D-479D394B2AAF}',{$ENDIF}3);
517           pdesc.selected:=false;
518           pdesc.pobject:=nil;
519 
520           pdesc.pointtype:=os_begin;
521           pdesc.attr:=[CPA_Strech];
522           pdesc.worldcoord:=q0;
523           {pdesc.dispcoord.x:=round(Pq0.x);
524           pdesc.dispcoord.y:=round(Pq0.y);}
525           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
526 
527           pdesc.pointtype:=os_midle;
528           pdesc.attr:=[];
529           pdesc.worldcoord:=q1;
530           {pdesc.dispcoord.x:=round(Pq1.x);
531           pdesc.dispcoord.y:=round(Pq1.y);}
532           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
533 
534           pdesc.pointtype:=os_end;
535           pdesc.attr:=[CPA_Strech];
536           pdesc.worldcoord:=q1;
537           {pdesc.dispcoord.x:=round(Pq2.x);
538           pdesc.dispcoord.y:=round(Pq2.y);}
539           PSelectedObjDesc(tdesc)^.pcontrolpoint^.PushBackData(pdesc);
540 end;
GDBObjEllipse.getsnapnull541 function GDBObjEllipse.getsnap;
542 //var t,d,e:GDBDouble;
543   //  tv,n,v:gdbvertex;
544 begin
545      if onlygetsnapcount=3 then
546      begin
547           result:=false;
548           exit;
549      end;
550      result:=true;
551      case onlygetsnapcount of
552      0:begin
553             if (SnapMode and osm_endpoint)<>0
554             then
555             begin
556             osp.worldcoord:=q0;
557             pgdbvertex2d(@osp.dispcoord)^:=pgdbvertex2d(@pq0)^;
558             osp.ostype:=os_begin;
559             end
560             else osp.ostype:=os_none;
561        end;
562      1:begin
563             if (SnapMode and osm_midpoint)<>0
564             then
565             begin
566             osp.worldcoord:=q1;
567             pgdbvertex2d(@osp.dispcoord)^:=pgdbvertex2d(@pq1)^;
568             osp.ostype:=os_midle;
569             end
570             else osp.ostype:=os_none;
571        end;
572      2:begin
573             if (SnapMode and osm_endpoint)<>0
574             then
575             begin
576             osp.worldcoord:=q2;
577             pgdbvertex2d(@osp.dispcoord)^:=pgdbvertex2d(@pq2)^;
578             osp.ostype:=os_end;
579             end
580             else osp.ostype:=os_none;
581        end;
582      end;
583      inc(onlygetsnapcount);
584 end;
GDBObjEllipse.beforertmodifynull585 function GDBObjEllipse.beforertmodify;
586 begin
587      GDBGetMem({$IFDEF DEBUGBUILD}'{77AF2FA4-2EDC-46CD-A813-6E34E2AC91A5}',{$ENDIF}result,sizeof(tellipsertmodify));
588      tellipsertmodify(result^).p1.x:=q0.x;
589      tellipsertmodify(result^).p1.y:=q0.y;
590      tellipsertmodify(result^).p2.x:=q1.x;
591      tellipsertmodify(result^).p2.y:=q1.y;
592      tellipsertmodify(result^).p3.x:=q2.x;
593      tellipsertmodify(result^).p3.y:=q2.y;
594 end;
GDBObjEllipse.IsRTNeedModifynull595 function GDBObjEllipse.IsRTNeedModify(const Point:PControlPointDesc; p:GDBPointer):Boolean;
596 begin
597      result:=true;
598 end;
599 procedure GDBObjEllipse.rtmodifyonepoint(const rtmod:TRTModifyData);
600 var a,b,c,d,e,f,g,p_x,p_y,rrr:GDBDouble;
601     tv:gdbvertex2d;
602     ptdata:tellipsertmodify;
603 begin
604      ptdata.p1.x:=q0.x;
605      ptdata.p1.y:=q0.y;
606      ptdata.p2.x:=q1.x;
607      ptdata.p2.y:=q1.y;
608      ptdata.p3.x:=q2.x;
609      ptdata.p3.y:=q2.y;
610 
611           case rtmod.point.pointtype of
612                os_begin:begin
613                              ptdata.p1.x:=q0.x+rtmod.dist.x;
614                              ptdata.p1.y:=q0.y+rtmod.dist.y;
615                         end;
616                os_midle:begin
617                              ptdata.p2.x:=q1.x+rtmod.dist.x;
618                              ptdata.p2.y:=q1.y+rtmod.dist.y;
619                       end;
620                os_end:begin
621                              ptdata.p3.x:=q2.x+rtmod.dist.x;
622                              ptdata.p3.y:=q2.y+rtmod.dist.y;
623                         end;
624           end;
625         A:= ptdata.p2.x - ptdata.p1.x;
626         B:= ptdata.p2.y - ptdata.p1.y;
627         C:= ptdata.p3.x - ptdata.p1.x;
628         D:= ptdata.p3.y - ptdata.p1.y;
629 
630         E:= A*(ptdata.p1.x + ptdata.p2.x) + B*(ptdata.p1.y + ptdata.p2.y);
631         F:= C*(ptdata.p1.x + ptdata.p3.x) + D*(ptdata.p1.y + ptdata.p3.y);
632 
633         G:= 2*(A*(ptdata.p3.y - ptdata.p2.y)-B*(ptdata.p3.x - ptdata.p2.x));
634         if abs(g)>eps then
635         begin
636         p_x:= (D*E - B*F) / G;
637         p_y:= (A*F - C*E) / G;
638         rrr:= sqrt(sqr(ptdata.p1.x - p_x) + sqr(ptdata.p1.y - p_y));
639         rr:=rrr;
640         Local.p_insert.x:=p_x;
641         Local.p_insert.y:=p_y;
642         Local.p_insert.z:=0;
643         tv.x:=p_x;
644         tv.y:=p_y;
645         startangle:=vertexangle(tv,ptdata.p1);
646         endangle:=vertexangle(tv,ptdata.p3);
647         if startangle>endangle then
648         begin
649                                                                                       rrr:=startangle;
650                                                                                       startangle:=endangle;
651                                                                                       endangle:=rrr
652         end;
653         rrr:=vertexangle(tv,ptdata.p2);
654         if (rrr>startangle) and (rrr<endangle) then
655                                                                                  begin
656                                                                                  end
657                                                                              else
658                                                                                  begin
659                                                                                       rrr:=startangle;
660                                                                                       startangle:=endangle;
661                                                                                       endangle:=rrr
662                                                                                  end;
663         //format;
664         //renderfeedback(gdb.GetCurrentDWG.pcamera^.POSCOUNT,gdb.GetCurrentDWG.pcamera^,nil);
665         end;
666 
667 end;
GDBObjEllipse.Clonenull668 function GDBObjEllipse.Clone;
669 var tvo: PGDBObjEllipse;
670 begin
671   GDBGetMem({$IFDEF DEBUGBUILD}'{368BA81A-219B-4DE9-A8E0-64EE16001126}',{$ENDIF}GDBPointer(tvo), sizeof(GDBObjEllipse));
672   tvo^.init(bp.ListPos.owner,vp.Layer, vp.LineWeight, Local.p_insert, {r,}startangle,endangle,majoraxis);
673   CopyVPto(tvo^);
674   //tvo^.vp.ID:=GDBEllipseID;
675   tvo^.Local:=local;
676   tvo^.RR:=RR;
677   tvo^.MajorAxis:=MajorAxis;
678   tvo^.Ratio:=Ratio;
679 
680   //tvo^.format;
681   result := tvo;
682 end;
683 procedure GDBObjEllipse.rtsave;
684 begin
685   PGDBObjEllipse(refp)^.Local.p_insert := Local.p_insert;
686   PGDBObjEllipse(refp)^.startangle := startangle;
687   PGDBObjEllipse(refp)^.endangle := endangle;
688   PGDBObjEllipse(refp)^.RR:=RR;
689   PGDBObjEllipse(refp)^.MajorAxis:=MajorAxis;
690   PGDBObjEllipse(refp)^.Ratio:=Ratio;
691   //PGDBObjEllipse(refp)^.format;
692   //PGDBObjEllipse(refp)^.renderfeedback(gdb.GetCurrentDWG.pcamera^.POSCOUNT,gdb.GetCurrentDWG.pcamera^,nil);
693 end;
AllocEllipsenull694 function AllocEllipse:PGDBObjEllipse;
695 begin
696   GDBGetMem({$IFDEF DEBUGBUILD}'{AllocEllipse}',{$ENDIF}result,sizeof(GDBObjEllipse));
697 end;
AllocAndInitEllipsenull698 function AllocAndInitEllipse(owner:PGDBObjGenericWithSubordinated):PGDBObjEllipse;
699 begin
700   result:=AllocEllipse;
701   result.initnul{(owner)};
702   result.bp.ListPos.Owner:=owner;
703 end;
GDBObjEllipse.CreateInstancenull704 function GDBObjEllipse.CreateInstance:PGDBObjEllipse;
705 begin
706   result:=AllocAndInitEllipse(nil);
707 end;
708 begin
709   RegisterDXFEntity(GDBEllipseID,'ELLIPSE','Ellipse',@AllocEllipse,@AllocAndInitEllipse);
710 end.
711