Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   NToBE ? (https://www.delphipraxis.net/179354-ntobe.html)

Bjoerk 2. Mär 2014 09:29

NToBE ?
 
Ich hab folgenden (wohl FreePascal) Code. Da gibst eine (vermutlich) function NToBE.
Kennt die jemand?

Delphi-Quellcode:
procedure DecodeASCII85(ASource: string; var ADest: TFPVUByteArray);
var
  CurSrcPos, CurDestPos: Integer;
  lDataDWordPtr: PCardinal;
  lDataCurChar: Char;
begin
  SetLength(ADest, 0);
  CurDestPos := 0;

  CurSrcPos := 1;
  while CurSrcPos <= Length(ASource) do
  begin
    lDataCurChar := ASource[CurSrcPos];

    // Compressed block of zeroes
    if lDataCurChar = 'z' then
    begin
      SetLength(ADest, Length(ADest)+4);
      ADest[CurDestPos] := 0;
      ADest[CurDestPos+1] := 0;
      ADest[CurDestPos+2] := 0;
      ADest[CurDestPos+3] := 0;
      Inc(CurDestPos, 4);
      Inc(CurSrcPos, 1);
      Continue;
    end;

    // Common block of data: 5 input bytes generate 4 output bytes
    SetLength(ADest, Length(ADest)+4);
    lDataDWordPtr := @(ADest[CurDestPos]);
    if CurSrcPos+4 <= Length(ASource) then
    begin
      lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
       + (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
       + (Byte(ASource[CurSrcPos+3])-33)*85 + (Byte(ASource[CurSrcPos+4])-33);
      lDataDWordPtr^ := NToBE(lDataDWordPtr^);
    end
    else if CurSrcPos+3 <= Length(ASource) then
    begin
      lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
       + (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
       + (Byte(ASource[CurSrcPos+3])-33)*85 + (Byte('u')-33);
      lDataDWordPtr^ := NToBE(lDataDWordPtr^);
      SetLength(ADest, Length(ADest)-1);
    end
    else if CurSrcPos+2 <= Length(ASource) then
    begin
      lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
       + (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte(ASource[CurSrcPos+2])-33)*85*85
       + (Byte('u')-33)*85 + (Byte('u')-33);
      lDataDWordPtr^ := NToBE(lDataDWordPtr^);
      SetLength(ADest, Length(ADest)-2);
    end
    else if CurSrcPos+1 <= Length(ASource) then
    begin
      lDataDWordPtr^ := (Byte(ASource[CurSrcPos])-33)*85*85*85*85
       + (Byte(ASource[CurSrcPos+1])-33)*85*85*85 + (Byte('u')-33)*85*85
       + (Byte('u')-33)*85 + (Byte('u')-33);
      lDataDWordPtr^ := NToBE(lDataDWordPtr^);
      SetLength(ADest, Length(ADest)-3);
    end
    else
    begin
      raise Exception.Create('[DecodeASCII85] Too few bytes remaining to decode!');
    end;

    Inc(CurDestPos, 4);
    Inc(CurSrcPos, 5);
  end;
end;

himitsu 2. Mär 2014 09:45

AW: NToBE ?
 
Wenn du denkst zu wissen wo es her ist, dann schau da doch mal nach?

http://www.freepascal.org/docs-html/...tem/ntobe.html


PS: Man hätte natürlich auch da nachfragen können, wo man den Code her hat und ansonsten kann es nie schaden uns zu verraten von wo das kommt.

Bjoerk 2. Mär 2014 10:17

AW: NToBE ?
 
Klar, hätte ich machen können, aber schließlich seid doch ihr hier meine Liebsten (Delphianer).:)

Ist von dort.

Falls jemand Zeit und Lust hat mitzumachen, ich schreibe gerade den dxfreader nach Delphi um (Ist mit Abstand der Beste was ich der Richtung bisher in Delphi gesehen habe?).

Man braucht dazu die fpvutils, fpvectorial und dxfvectorialreader von dort.

Jens01 2. Mär 2014 14:28

AW: NToBE ?
 
Habe mir das DXF-Ding gerade mal angeguckt.
Brauchst Du dies "DecodeASCII85" für die DXF überhaupt?

Bjoerk 2. Mär 2014 18:26

AW: NToBE ?
 
Hi Bud. Nee, brauch ich nich, war mir aber heute morgen noch nicht bewußt. Das Ding ist übrigens vom dxf-fachlichen her echt gut aber die ganzen Results der functions als Klassen machen einem echt fertig. :shock:

Mach ich Records draus /wenn's geht oder ich schmeiß sie ganz raus weil ich ja nicht rendern muß sondern die Daten nur in meine Objecte einlesen muß. Ansonsten hat mir mein C++ Kumpel aus Freiburg auch versprochen, ggf. einen aktuellen Parser von C/ C++ (gibt’s anscheinend mehre Open Source Projekte) nach Delphi zu übersetzen.

Jens01 2. Mär 2014 19:03

AW: NToBE ?
 
Also die Qualität kann ich so gerade nicht beurteilen, aber es muß wohl etwas umgeschrieben werden. Und irgendeine Art "Schnittstelle" mußte ja haben.

Hast Du Dich über diese LGPL-Lizenz informiert? Kann man die kommerziell einsetzen?

Bjoerk 2. Mär 2014 20:29

AW: NToBE ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Jo. Das kann man so nicht verwenden. Ich habs mal laufen lassen. Wahnsinn (Siehe Anlage). Ich werd die units fpvutils und fpvectorial ganz rauschmeißen und nur die 3 Klassen TDXFToken, TDXFTokenizer und die TvDXFVectorialReader aus der dxfreader verwenden. Die ReadENTITIES bekommen das entsprechende Objekt meiner Software und ein Event um das einer Liste hinzuzufügen.
Wegen der Lizenz. Ich verwende grundsätzlich nichts was nicht abgeklärt ist. Normalerweise mache ich’s so, daß ich dem Autor eine Mail mit der überabeiteten unit schicke und frage an ob ich die so (auch ggf. kommerziell) verwenden kann. Dann kommt in aller Regel ein no poblem und es freut mich, daß sich überhaut mal jemand dafür interessiert.

Jens01 2. Mär 2014 22:30

AW: NToBE ?
 
Zitat:

Die ReadENTITIES bekommen das entsprechende Objekt meiner Software und ein Event um das einer Liste hinzuzufügen.
Man könnte auch jedem ReadENTITY ein spezielles Event zuordnen, wo gleichzeitig die Parameter übergeben werden. Dann ist das noch etwas mehr gekapselt. -Hab sowas mal mit einem experimentellen Parser gemacht-

Edit:
Hab gerade gesehen, dass da hierarchische Strukturen enthalten sind, so dass mein Ansatz nicht so richtig geht und Deiner etwas komplizierter wird. Glaube ich jetzt mal so...
Edit: Geht doch..

Bjoerk 3. Mär 2014 14:01

AW: NToBE ?
 
Wenn man die Insert rausschmeißt geht's, ansonsten braucht man eine Liste innerhalb des Parsers.

BTW: Hast du die Einleseroutine verstanden? Wenn ja wie kommen FloatValue und
IntValue in die DxfItems, da wird später nämlich munter drauf zugegriffen, ich sehe aber kein Einlesen? :gruebel:

Delphi-Quellcode:
  TDxfToken = class
  public
    GroupCode: integer;
    StrValue: string;
    FloatValue: double;
    IntValue: integer;
    Childs: TList;
    procedure Clear;
    constructor Create;
    destructor Destroy; override;
  end;

  TDxfTokenizer = class
  public
    Tokens: TList;
    function TablesSubsection(const Value: string): boolean;
    function BlocksSubsection(const Value: string): boolean;
    function EntitiesSubsection(const Value: string): boolean;
    procedure LoadFromFile(const FileName: string);
    procedure Clear;
    constructor Create;
    destructor Destroy; override;
  end;


procedure TDxfTokenizer.LoadFromFile(const FileName: string);
var
  I: integer;
  StrSectionGroupCode, StrSectionName: string;
  IntSectionGroupCode: integer;
  CurTokenBase, NextTokenBase, SectionTokenBase, LastBlockToken: TList;
  NewToken: TDxfToken;
  ParserState: integer;
  SL: TStringList;
begin
  if FileExists(FileName) then
  begin
    SL := TStringList.Create;
    try
      Tokens.Clear;
      SL.LoadFromFile(FileName);

      CurTokenBase := Tokens;
      NextTokenBase := Tokens;
      I := 0;
      ParserState := 0;

      while I < SL.Count - 1 do
      begin
        CurTokenBase := NextTokenBase;

        // Now read and process the section name
        StrSectionGroupCode := SL.Strings[I];
        IntSectionGroupCode := StrToInt(Trim(StrSectionGroupCode));
        StrSectionName := SL.Strings[I + 1];

        NewToken := TDxfToken.Create;
        NewToken.GroupCode := IntSectionGroupCode;
        NewToken.StrValue := StrSectionName;

        // Waiting for a section
        if ParserState = 0 then
        begin
          if (StrSectionName = 'SECTION') then
          begin
            ParserState := 1;
            NextTokenBase := NewToken.Childs;
          end
          else
            if (StrSectionName = 'EOF') then
            begin
              Exit;
            end
            // Comments can be in the beginning of the file and start with 999
            else
              if (IntSectionGroupCode = 999) then
              begin
                // nothing to be done, let it add the token
              end
              else
              begin
                raise Exception.Create(Format(
                  'TDxfTokenizer.ReadFromStrings: Expected SECTION, but got: %s', [StrSectionname]));
              end;
        end
        // Processing the section name
        else
          if ParserState = 1 then
          begin
            if (StrSectionName = 'HEADER') or
              (StrSectionName = 'CLASSES') or
              (StrSectionName = 'OBJECTS') or
              (StrSectionName = 'THUMBNAILIMAGE') then
            begin
              ParserState := 2;
              SectionTokenBase := CurTokenBase;
            end
            else
              if (StrSectionName = 'BLOCKS') or (StrSectionName = 'TABLES') then
              begin
                ParserState := 4;
                SectionTokenBase := CurTokenBase;
              end
              else
                if (StrSectionName = 'ENTITIES') then
                begin
                  ParserState := 3;
                  SectionTokenBase := CurTokenBase;
                end
                else
                begin
                  raise Exception.Create(Format(
                    'TDxfTokenizer.ReadFromStrings: Invalid section name: %s', [StrSectionname]));
                end;
          end
          // Reading a generic section
          else
            if ParserState = 2 then
            begin
              if StrSectionName = 'ENDSEC' then
              begin
                ParserState := 0;
                CurTokenBase := SectionTokenBase;
                NextTokenBase := Tokens;
              end;
            end
            // Reading the ENTITIES section
            else
              if ParserState = 3 then
              begin
                if EntitiesSubsection(StrSectionName) then
                begin
                  CurTokenBase := SectionTokenBase;
                  NextTokenBase := NewToken.Childs;
                end
                else
                  if StrSectionName = 'ENDSEC' then
                  begin
                    ParserState := 0;
                    CurTokenBase := SectionTokenBase;
                    NextTokenBase := Tokens;
                  end;
              end
              // Reading the TABLES or BLOCKS sections
              else
                if ParserState = 4 then
                begin
                  // This orders the blocks themselves
                  if TablesSubsection(StrSectionName) or BlocksSubsection(StrSectionName) then
                  begin
                    CurTokenBase := SectionTokenBase;
                    NextTokenBase := NewToken.Childs;
                    LastBlockToken := NewToken.Childs;
                  end
                  // This orders the entities inside blocks
                  else
                    if EntitiesSubsection(StrSectionName) and (LastBlockToken <> nil) then
                    begin
                      CurTokenBase := LastBlockToken;
                      NextTokenBase := NewToken.Childs;
                    end
                    else
                      if StrSectionName = 'ENDSEC' then
                      begin
                        ParserState := 0;
                        CurTokenBase := SectionTokenBase;
                        NextTokenBase := Tokens;
                      end;
                end;
        CurTokenBase.Add(NewToken);
        Inc(I, 2);
      end;
    finally
      SL.Free;
    end;
  end;
end;

Jens01 3. Mär 2014 14:14

AW: NToBE ?
 
über dies StrValue in ReadFromStrings?

Bjoerk 3. Mär 2014 14:40

AW: NToBE ?
 
Das ist doch qausi die ReadFromStrings? Hab jetzt aber gesehen, daß zunächst alles erstmal in den StrValue geladen wird. Der Item braucht eigentlich keinen FloatValuem, die können auch lokale Variablen in den Read ReadEntities_XY sein.

implementation 3. Mär 2014 14:52

AW: NToBE ?
 
Bezüglich der LGPL:
Der Code ist freie Software, du kannst ihn also problemlos zu jedem Zweck verwenden und zu jedem Preis weitergeben/verkaufen. Es greift allerdings bibliothekweites Copyleft, d.h. wenn du am Code etwas änderst oder hinzufügst, gelten die LGPL-Klauseln auch für deine Veränderungen. Dies greift aber nicht mehr auf ein Programm, das diese Bibliothek nur einbindet. Dynamisches Linken ist völlig problemlos, da muss dich das Copyleft nicht stören, statisches eigentlich auch, mit der Einschränkung dass du die ungelinkten *.o/*.obj-Dateien auch vom restlichen Programm mitliefern musst, damit der Nutzer bei Bedarf das Programm gegen eine neuere Version der Bibliothek linken kann. Nun ist die FreePascal-Lizenz aber keine unveränderte LGPL, sondern es hängt noch eine zusätzliche Klausel dran, die sagt, dass du genau das nicht brauchst :wink:

TL;DR: Wenn du die Bibliothek nur einbindest, kannst du praktisch machen was du willst; wenn du sie veränderst oder ergänzt, unterliegst du dem Copyleft.

Ich habe auch mal eine Auflistung zu dem Thema gemacht.

Bjoerk 3. Mär 2014 20:03

AW: NToBE ?
 
Um alle Tokens freigeben zu können hab ich eine zweite Liste (*** Stack) mitlaufen. Das geht aber doch auch anders (ist doch so ein verkette Listen Zeugs). Wie macht denn nochmal sowas? :oops:

Delphi-Quellcode:
procedure TDxfTokenizer.LoadFromFile(const FileName: string);
begin
  if FileExists(FileName) then
  begin
    ..
    SL := TStringList.Create;
    try
      SL.LoadFromFile(FileName);
      ..
      while I < SL.Count - 1 do
      begin
        ...
        NewToken := TDxfToken.Create;
        NewToken.Group := IntSectionGroupCode;
        NewToken.Name := StrSectionName;
        FList.Add(NewToken); // ***



destructor TDxfTokenizer.Destroy;
begin
  Clear;
  FList.Free;
  Tokens.Free;
  inherited Destroy;
end;

procedure TDxfTokenizer.Clear;
var
  I: integer;
  Token: TDxfToken;
begin
  for I := FList.Count - 1 downto 0 do // ***
  begin
    Token := TDxfToken(FList[I]);
    Token.Free;
  end;
  FList.Clear;
  Tokens.Clear;
end;

Jens01 3. Mär 2014 20:12

AW: NToBE ?
 
Ich glaube das ist sowas wie ein Octree.
Wenn Du eine Objectlist nimmst, dann sollten sich die Objekte in der Liste beim Befreien der Liste selbst befreien. (verstanden?)

Bjoerk 3. Mär 2014 20:27

AW: NToBE ?
 
Tatsächlich. Hätt ich nicht gedacht. Den einen NewToken der nicht gebraucht wird (der bei EOF muß man allerdings selbst freigeben). Dann geht’s. Thanx!

BWT, was ist ein Octree?

Ich lese den Code so daß es zu jedem Token einen oder mehrere Childs geben kann, aber keine Child.Childs.. Also quasi Verzeichnisse mit einem oder mehren Unterverzeichnissen auf der 1. Ebene.

Jens01 3. Mär 2014 20:46

AW: NToBE ?
 
Ich weiß jetzt nicht, ob es im Code so gemacht wird, aber jeder Knoten in der Knotenliste hat wieder eine Knotenliste. Also die Struktur ist schon wie ein Octree, wo zumindest eine endlose Tiefe möglch wäre.
wiki octree

Bjoerk 3. Mär 2014 21:04

AW: NToBE ?
 
Genau. Jeder Knoten hat EINE Knotenliste. Ich denke aber sowieso, daß der Erfinder der dxf Struktur eigentlich gesteinigt gehört. Schau dir nur mal diese POLYLINE VERTEX SEQEND Konstruktion an. Eigentlich DAS Paradebeispiel für eine Inifile Struktur. Was man so hört wollte Autodesk schon lange auch mal umstellen?

Jens01 3. Mär 2014 21:14

AW: NToBE ?
 
Darauf stellen jetzt alle um.

Bjoerk 7. Mär 2014 10:42

AW: NToBE ?
 
Hast du mal was gefunden zum konvertieren von dxf bin nach dxf ascii?

Jens01 7. Mär 2014 11:16

AW: NToBE ?
 
Hab noch gar nicht gewußt, dass es sowas gibt.
Hast Du eine Beispieldatei?

Bjoerk 7. Mär 2014 12:20

AW: NToBE ?
 
Nee. Stop. Scheint irgendwie doch ASCII Format zu sein, aber ohne richtiges FormFeed. Im Editor sah das auf den ersten Blick nur so aus. Sorry. TStringList liest sie aber dennoch korrekt ein.

BTW, bin mit meinem Parser fertig, bin aber dennoch unzufrieden. Irfanview ist schon noch besser. Hab mir aber sagen lassen daß die "Anderen" dxf Files auch nur mit erheblichen Verlusten einlesen. Gibt in Mannheim so ein AutoLISP Freak der auch Kunde von mir ist. Den ruf ich mal an.

Jens01 7. Mär 2014 13:15

AW: NToBE ?
 
Was willst Du von einem Parser mit rund 2000 Codezeilen verlangen. Ich glaube, wenn Du einen richtig guten haben willst, wird der Aufwand überproportional größer.

Bjoerk 7. Mär 2014 13:43

AW: NToBE ?
 
Ja sicher. Stimmt, sind auch ziemlich genau 2000 Zeilen.:-D

Ärgert mich aber trotzdem. Die Struktur haben die FreePascal Autoren ja wirklich sehr schön herausgearbeitet. Läuft auch (wesentlich) stabiler als zum Beispiel der Parser von John Biddiscombe (DXF_read und Co). Bis dato hatte ich auch noch keine Exception beim Einlesen. Der Rest ist wohl noch etwas Fleißarbeit. Ist ja irgendwie immer nur das Gleiche.
Beispiel ReadEntities_LINE:
Delphi-Quellcode:
procedure TDxfParser.ReadEntities_LINE(ATokens: TObjectList; const Base: TFloatPointD2);
var
  Current: TDxfToken;
  I: integer;
  X1, Y1, X2, Y2, Value: double;
  Color: TColor;
begin
  X1 := 0;
  Y1 := 0;
  X2 := 0;
  Y2 := 0;
  Color := clBlack;
  for I := 0 to ATokens.Count - 1 do
  begin
    Current := TDxfToken(ATokens[I]);
    if Current.Group in [10, 20, 11, 21, 62] then
    begin
      Value := StrToFloat(Trim(Current.Name));
      case Current.Group of
        10: X1 := Base.X + Value;
        20: Y1 := Base.Y + Value;
        11: X2 := Base.X + Value;
        21: Y2 := Base.Y + Value;
        62: Color := FAutoCadColorPalette[Round(Value)];
      end;
    end;
  end;
  FItem.Clear;
  FItem.Typ := dxfLINE;
  FItem.BlockName := FBlockName;
  FItem.Pen.Color := Color;
  FItem.Points.Add(FloatPointD2(X1, Y1));
  FItem.Points.Add(FloatPointD2(X2, Y2));
  // ShowMessage(Format('%s %f %f %f %f', [FBlockName, X1, Y1, X2, Y2]));
  if Assigned(FOnGetDxfItem) then
    FOnGetDxfItem(FItem);
end;

Jens01 7. Mär 2014 22:02

AW: NToBE ?
 
Mit den Events meinte ich das etwas anders.
Wenn das Event ungefähr so aussehen würde ohne dies "FItem"
Delphi-Quellcode:
// FItem hier ganz rauswerfen
if Assigned(FOnDXFLine) then
    FOnDXFLine(Self, Blockname, Color, FloatPointD2(X1, Y1), FloatPointD2(X2, Y2));
Dann würdest Du diese DXF-Sache komplett von deinem Programm abgrenzen.
Die graphische Darstellung würde etwa so aussehen :
Delphi-Quellcode:
procedure OnDXFLine(Sender: TObject; Name:string; Color:Tcolor; P1, P2: TPoint);
begin
  FMeineGraphikListe.AddLine(Color, P1, P2);
  FMeineGraphikListe.Draw;
  // oder so ähnlich
end;
Hinsichtlich OOP-Optimierung mußt Du sonst halt Christian fragen :zwinker:

Bjoerk 7. Mär 2014 22:57

AW: NToBE ?
 
Der ParserItem hat mit meiner Software nichts am Hut. Mit deinem Hinweis den Parser von der restlichen Software zu entkoppeln hattest du völlig Recht und so hab ich's auch gemacht. Die ReadHeader hab ich übrigens ganz neu aufgesetzt. BTW, kennst du das?

Jens01 7. Mär 2014 23:06

AW: NToBE ?
 
Okay, dann habe ich Deine Code falsch verstanden. War ja auch nur ein kleiner Ausschnitt.
Nee, Buch kenne ich nicht. Habe mich aber mit DXF in der Art auch noch nicht auseinandergesetzt.
Eigentlich kauft man sich solch eine Komponente ja auch günstig ein. In der Delphi-Welt scheint es das aber nicht zu geben.

Jens01 7. Mär 2014 23:20

AW: NToBE ?
 
Habe gerade mal die Bücher geguckt. Das mit dem Bild kostet bei Amazon gebraucht Euro 200,--
Stolzer Preis!

Problem bei den Dingern ist wohl, die sind uralt. Die Standards habe sich -glaube ich- schon etwas verändert. Zum Schluß bist Du nach dem Lesen des Buches wieder auf dem Stand Deines eigenen Parsers.

Bjoerk 8. Mär 2014 09:45

AW: NToBE ?
 
Jo, scheint irgendwie Kultstatuts zuhaben? Ich hab mir DXF intern bestellt. "DXF intern ist eine korrigierte und erweiterte Neuauflage des seit einiger Zeit ausverkauften Referenzbuchs Der DXF-Standard". Kostet (neu) auch nur die Hälfte (als das alte gebraucht). :)

Mir geht es auch nicht darum die 500 Seiten durchzuackern sondern nachzuschauen was ich (noch) brauch und um Unklarheiten zu beseitigen. Was ist z.B. der Unterschied zwischen ExtMax/Min und LimMax/Min. Was bedeutet InsBase? Wie sind z.B. die diversen Skalierungsfaktoren und Ratationsangles zu verstehen? Und sind die bei Blöcken additiv usw..

Jens01 8. Mär 2014 11:06

AW: NToBE ?
 
Das könnte auch schon helfen.

Zitat:

Jo, scheint irgendwie Kultstatuts zuhaben?
Nee, gucke öfter nach guten, alten Büchern. Wenn die etwas knapp sind, versucht einer immer die für solche Preise an den Mann zu bringen.

Bjoerk 8. Mär 2014 14:49

AW: NToBE ?
 
Hey, danke. Hab schon mal nach der auf deutsch gesucht. Unter Google hab ich mich doch gewundert warum "dxf reference german" die nicht findet?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz