TsgDXFImage.create processor time

Discuss and ask questions about CAD VCL (Delphi and C++ Builder).

Moderators: SDS, support, admin

Post Reply
gnl
Posts: 9
Joined: 05 Oct 2006, 23:40
Location: Greece

TsgDXFImage.create processor time

Post by gnl » 19 Oct 2006, 23:30

Dear Sergey,

I use the following code, in order to show on my application's main image some instruments that the user has entered into a database. The number of these instruments is in the range of 3000 distinct items. I have run a few time benchmarks on this code, as you can see from the outputdebugstring and I have noticed that it takes about 80 msecs for the TsgDXFImage.Create method to complete!! I know that this is not a long time but if you multiply 3000*80 = 240000/1000 = 240 secs, that is 4 minutes only for the TsgDXFImage create part!! I was wondering if there is another way of achieving the same result, in other words being able to load an external file only once and then just copy it as many times as needed without going through the TsgDXFImage.create part, in order to improve performance?

Kind regards
George

Code: Select all

<b>procedure</b> TfrmMain.AddInstrumentDwg(Instrument : TgnlInstrument; qry : Tquery);
<b>var</b>
 v : TsgDXFImage;
 t : TsgDXFText;
 vIns: TsgDXFInsert;
 Tm,Tmf : TDateTime;
 TotalTm : Double;
 i : Integer;
 IDR : TgnlInstrumentDrawingRecord;
<b>begin</b>
  tmf := now;

  v := TsgDXFImage.Create;
  OutputDebugString(PChar(<font color="blue">'After TsgDXFImage.Create '</font id="blue">+FloatToStr(MillisecondsBetween(now,tmf))));

  v.IsWithoutBorder := True;
  TsgDXFImage(v).LoadFromFile(qry.FieldByName(<font color="blue">'INSTR_DWG_FILE'</font id="blue">).asString);
  v.GetExtents;
  vIns :=
   Img.AddScaledDXFEx
   (
    v,                  <i><font color="blue">// TsgDXFImage object for inserting</font id="blue"></i>
    INSERT_PREFIX+Instrument.INSTR_UID, <i><font color="blue">// Name</font id="blue"></i>
    MakeFPoint(Instrument.INSTR_X-v.Extents.Left-(qry.FieldByName(<font color="blue">'INSTR_DWG_HOTSPOTX'</font id="blue">).asInteger-v.Extents.Left),
      Instrument.INSTR_Y-v.Extents.Bottom-(qry.FieldByName(<font color="blue">'INSTR_DWG_HOTSPOTY'</font id="blue">).asInteger-v.Extents.Bottom), 0.0),  <i><font color="blue">// position in ACAD coords</font id="blue"></i>
    MakeFPoint(1, 1, 1),         <i><font color="blue">// scale factor</font id="blue"></i>
    0.0                          <i><font color="blue">// rotation angle (degrees)</font id="blue"></i>
   );
  Img.GetExtents;

  IDR := TgnlInstrumentDrawingRecord.Create;
  IDR.InstumentType := Instrument.INSTR_TYPE;
  IDR.DXFInsert := vIns;

  fInstrumentList.Add(IDR);  <i><font color="blue">// save added Insert entiry in the list</font id="blue"></i>

  tm := now;
  t := TsgDXFText.Create;
  t.Text := Instrument.INSTR_UID;
  t.Height := 1;
  t.Point := MakeFPoint(Instrument.INSTR_X+(v.Extents.Right-v.Extents.Left), Instrument.INSTR_Y, 0);
  t.SetColor(clRed);
  t.SetLWeight(1);
  t.Scale := 1;
  <b>if</b> Assigned(Img.Converter.OnCreate) <b>then</b>
    Img.Converter.OnCreate(t);
  OutputDebugString(PChar(<font color="blue">'After TsgDXFText '</font id="blue">+FloatToStr(MillisecondsBetween(now,tm))));

  Img.Converter.Sections[csEntities].AddEntity(t);
  Img.Converter.Loads(t);
  fInstrumentTextList.Add(t);  <i><font color="blue">// save added Text entiry in the list</font id="blue"></i>

  Img.GetExtents;
  OutputDebugString(PChar(<font color="blue">'AddInstrumentDwg exit :'</font id="blue">+FloatToStr(MillisecondsBetween(now,tmf))));
<b>end</b>;

support
Posts: 3272
Joined: 30 Mar 2005, 11:36
Contact:

Post by support » 20 Oct 2006, 14:31

Dear George,

<ul><li>The following line is not necessary:

Code: Select all

v.GetExtents
</li>
<li>Call

Code: Select all

TsgDXFImage.GetExtents;
when you finish adding all XRefs.</li>
<li>You may duplicate loaded once <b>TsgDXFImage</b> using <b>TsgDXFInsert</b> returned by <b>TsgDXFImage.AddScaledDXFEx</b>. Please see the follwoing example:

Code: Select all

<b>type</b>
  TForm1 = <b>class</b>(TForm)
   ...
    sgImage1: TsgImage;
    btnAddXRefs: TButton;
    <b>procedure</b> btnAddXRefsClick(Sender: TObject);
  <b>private</b>
    FImg: TsgDXFImage;
...
<b>procedure</b> TForm.btnAddXRefsClick(Sender: TObject);
<b>var</b>
  vImg: TsgDXFImage;
  vIns, vIns2: TsgDXFInsert;
  vPoint: TFPoint;
  I: Integer;
<b>begin</b>
  sgImage1.LoadFromFile(<font color="blue">'c:\test.dxf'</font id="blue">);
  <b>if</b> sgImage1.Picture.Graphic <b>is</b> TsgDXFImage <b>then
  begin</b>
    FImg := TsgDXFImage(sgImage1.Picture.Graphic);
    sgImage1.Align := alClient;
  <b>end
  else
  begin</b>
    FImg := <b>nil</b>;
    Exit;
  <b>end</b>;

  vPoint := MakeFPoint(FImg.Extents.Left, FImg.Extents.Bottom, <font color="blue">0</font id="blue">);
  vImg := TsgDXFImage.Create;
  vImg.LoadFromFile(<font color="blue">'c:\inserted.dxf'</font id="blue">);
  vIns := FImg.AddScaledDXFEx(vImg,<font color="blue">'inserted'</font id="blue">,vPoint,MakeFPoint(<font color="blue">0.01</font id="blue">,<font color="blue">0.01</font id="blue">,<font color="blue">0.01</font id="blue">),<font color="blue">0.0</font id="blue">);

  <b>for</b> I := <font color="blue">0</font id="blue"> <b>to</b> <font color="blue">300</font id="blue"> <b>do
  begin</b>
    vIns2 := TsgDXFInsert.Create;
    vIns2.AssignEntity(vIns);
    vIns2.Point := MakeFPoint(vIns2.Point.X + <font color="blue">50</font id="blue"> * I,vIns2.Point.Y + <font color="blue">50</font id="blue"> * I,vIns2.Point.Z);
    FImg.Converter.Sections[csEntities].AddEntity(vIns2);
    <b>if</b> Assigned(FImg.Converter.OnCreate) <b>then</b>
      FImg.Converter.OnCreate(vIns2);
    FImg.Converter.Loads(vIns2);
  <b>end</b>;
  FImg.GetExtents;
<b>end</b>;
</li></ul>
Sergey.

please post questions to the forum or write to support@cadsofttools.com

gnl
Posts: 9
Joined: 05 Oct 2006, 23:40
Location: Greece

Post by gnl » 24 Oct 2006, 00:03

Dear Sergey,

Thank you for your hint, it has significantly improved the response time of my application, but I still need your help with turning off and deleting the entities after I am through with them. I get AVs when I try to free them and I assume that is because I am saving references to vIns and vIns2 and that causes the DXFimage to be freed more than once. I would greatly appreciate your help on the matter.

Kind regards
George

support
Posts: 3272
Joined: 30 Mar 2005, 11:36
Contact:

Post by support » 24 Oct 2006, 12:12

Dear George,

Here goes the modified code from the previous posting:

Code: Select all

<b>procedure</b> TForm1.btnAddXRefsClick(Sender: TObject);
<b>var</b>
  vImg: TsgDXFImage;
  vIns, vIns2: TsgDXFInsert;
  vPoint: TFPoint;
  I: Integer;
<b>begin</b>
  sgImage1.Visible := False;
  sgImage1.LoadFromFile(<font color="blue">'c:\test.dxf'</font id="blue">);
  <b>if</b> sgImage1.Picture.Graphic <b>is</b> TsgDXFImage <b>then
  begin</b>
    FImg := TsgDXFImage(sgImage1.Picture.Graphic);
    sgImage1.Align := alClient;
  <b>end
  else
  begin</b>
    FImg := <b>nil</b>;
    Exit;
  <b>end</b>;

  vPoint := MakeFPoint(FImg.Extents.Left, FImg.Extents.Bottom, <font color="blue">0</font id="blue">);
  vImg := TsgDXFImage.Create;
  vImg.LoadFromFile(<font color="blue">'c:\inserted.dxf'</font id="blue">);
  vIns := FImg.AddScaledDXFEx(vImg,<font color="blue">'Inserted'</font id="blue">,vPoint,MakeFPoint(<font color="blue">0.01</font id="blue">, <font color="blue">0.01</font id="blue">, <font color="blue">0.01</font id="blue">), <font color="blue">0.0</font id="blue">);

  <b>if</b> FXRefsList = <b>nil then</b>
    FXRefsList := TList.Create;
  <b>or</b> I := <font color="blue">0</font id="blue"> <b>to</b> <font color="blue">30</font id="blue"> <b>do
  begin</b>
    vIns2 := TsgDXFInsert.Create;
    vIns2.AssignEntity(vIns);
    vIns2.Point := MakeFPoint(vIns2.Point.X + <font color="blue">50</font id="blue"> * I,vIns2.Point.Y + <font color="blue">50</font id="blue"> * I,vIns2.Point.Z);
    FXRefsList.Add(vIns2);
    FImg.Converter.Sections[csEntities].AddEntity(vIns2);
    <b>if</b> Assigned(FImg.Converter.OnCreate) <b>then</b>
      FImg.Converter.OnCreate(vIns2);
    FImg.Converter.Loads(vIns2);
  <b>end</b>;
  FImg.GetExtents;
  sgImage1.Visible := True;

<b>end</b>;

<b>procedure</b> TForm1.btnDeleteXRefsClick(Sender: TObject);
<b>var</b>
  vInsert: TsgDXFInsert;
  I, J: Integer;
<b>begin</b>
  sgImage1.Visible := False;
  <b>if</b> (FXRefsList = <b>nil</b>) <b>and</b> (FImg = <b>nil</b>) <b>then</b>
    Exit;

  <b>for</b> I := FImg.Converter.Counts[csEntities] - <font color="blue">1</font id="blue"> <b>downto</b> <font color="blue">0</font id="blue"> <b>do
  begin
    if</b> FImg.Converter.Sections[csEntities].Entities[I] <b>is</b> TsgDXFInsert <b>then
    begin</b>
      vInsert := TsgDXFInsert(FImg.Converter.Sections[csEntities].Entities[I]);
      J := FXRefsList.IndexOf(vInsert);
      <b>if</b> J > -<font color="blue">1</font id="blue"> <b>then
      begin</b>
        vInsert.Block := <b>nil</b>;
        FImg.Converter.DeleteEntity(vInsert, True);
        FXRefsList.Delete(J);
      <b>end</b>;
    <b>end</b>;
  <b>end</b>;

  FXRefsList.Free;
  FImg.GetExtents;
  sgImage1.Visible := True;
<b>end</b>;
Sergey.

please post questions to the forum or write to support@cadsofttools.com

Post Reply