7.3. Σενάρια Pascal

Αυτό το κεφάλαιο είναι η πλήρης αναφορά του ενσωματωμένου host Pascal Script του IQcad: κάθε κλάση, καθολική συνάρτηση, εντολή και συμβάν που είναι διαθέσιμα στα σενάρια, με διάγραμμα κλάσεων σε μορφή κειμένου και πλήρη παραδείγματα.

Για τις γενικές έννοιες των σεναρίων (μοντέλο εμπιστοσύνης, αυτόματη φόρτωση, προσαρμοσμένες εντολές, συμβάντα) δείτε το Σενάρια Python στο κεφάλαιο 18 και την Αναφορά σεναρίων Python στο κεφάλαιο 19. Ο host Pascal μοιράζεται το ίδιο μοντέλο σχεδίου Layer-2 με την Python, οπότε οι έννοιες αυτές μεταφέρονται αυτούσιες· το παρόν κεφάλαιο τεκμηριώνει όσα είναι ειδικά για την Pascal.

7.3.1. Εισαγωγή

Το Pascal Script είναι ένας διερμηνέας με σύνταξη Pascal που μεταγλωττίζει το σενάριό σας μέσα στο IQcad κατά την εκτέλεση. Σε αντίθεση με τον host Python – ο οποίος ενσωματώνει έναν συνοδευτικό διερμηνέα CPython – ο host Pascal έχει καμία εξωτερική εξάρτηση εκτέλεσης: δεν υπάρχει τίποτα για εγκατάσταση και δεν συνοδεύει τίποτα το IQcad.exe. Αν γνωρίζετε ήδη Object Pascal (ή Delphi), αυτός είναι ο ευκολότερος τρόπος αυτοματοποίησης του IQcad.

Και οι δύο hosts επικοινωνούν με το ίδιο μοντέλο σχεδίου Layer-2: μια επιφάνεια, χάραξη ή οντότητα που δημιουργείται από Pascal είναι ίδια με αυτήν που δημιουργείται από Python ή από το GUI. Οι δύο γλώσσες διαφέρουν μόνο στη σύνταξη και στον τρόπο με τον οποίο διακινούν συλλογές (δείτε Το μοντέλο αντικειμένων).

7.3.2. Εκτέλεση Pascal

Τέσσερα σημεία εισόδου από τη γραμμή εντολών χειρίζονται τον host Pascal:

Εντολή

Περιγραφή

PASCAL <file.pas> (ψευδώνυμο PAS)

Εκτελεί ένα αρχείο .pas μία φορά. Ό,τι καταχωρίζει απορρίπτεται όταν τελειώσει (εκτός αν καταχωρίσει εντολή – τότε παραμένει φορτωμένο, όπως με το PASLOAD).

PASEVAL <expr>

Αποτιμά μία μόνο έκφραση Pascal και τυπώνει την τιμή της στη γραμμή εντολών (π.χ. PASEVAL ActiveDrawing.Name).

PASLOAD <file.pas>

Εκτελεί ένα αρχείο και το αφήνει φορτωμένο για τη συνεδρία: όσες εντολές ή χειριστές συμβάντων καταχωρίζει παραμένουν ενεργοί μέχρι να κλείσετε το IQcad.

PASSCRIPTS

Εμφανίζει τις εντολές που έχουν οριστεί σε Pascal και είναι καταχωρισμένες αυτή τη στιγμή.

Ένα σενάριο είναι ένα κανονικό program της Pascal:

program demo;
begin
  WriteLine('hello from Pascal');
end.

Ένα σκέτο απόσπασμα χωρίς επικεφαλίδα program ... begin ... end. περιτυλίγεται αυτόματα, οπότε το WriteLine('hi'); εκτελείται και μόνο του.

Σημείωση

Ο μηχανισμός περιτύλιξης αναγνωρίζει ένα πλήρες πρόγραμμα από την πρώτη λέξη-κλειδί program (ή unit), παραλείποντας τυχόν αρχικά σχόλια. Μπορείτε να ξεκινήσετε ένα αρχείο πλήρους προγράμματος με μπλοκ σχολίων επικεφαλίδας ({ ... }, // ή (* ... *)) πριν από τη γραμμή program, όπως κάνουν τα συνοδευτικά δείγματα.

7.3.2.1. Αυτόματη φόρτωση και εμπιστοσύνη

Κάθε αρχείο .pas που τοποθετείται στο %APPDATA%\IQcad\scripts\ φορτώνεται αυτόματα κατά την εκκίνηση, με το ίδιο μοντέλο εμπιστοσύνης βάσει hash περιεχομένου όπως η Python. Την πρώτη φορά που το IQcad συναντά ένα σενάριο (και ξανά κάθε φορά που αλλάζει το SHA-256 hash του περιεχομένου του) εμφανίζει έναν διάλογο εμπιστοσύνης που προσφέρει Always (πάντα), This session (αυτή τη συνεδρία) ή Never (ποτέ)· η επιλογή σας αποθηκεύεται στο %APPDATA%\IQcad\scripts\script_trust.json. Ένα σενάριο που δεν έχετε εμπιστευτεί ποτέ δεν εκτελείται.

7.3.2.2. Απόκριση και Esc

Τα σενάρια εκτελούνται στο νήμα του GUI. Σε κάθε βρόχο που μπορεί να διαρκέσει αρκετά, καλείτε περιοδικά το Yield: επεξεργάζεται την ουρά μηνυμάτων ώστε το παράθυρο να παραμένει αποκρίσιμο και επιτρέπει στο Esc να ακυρώσει το σενάριο. Η ακύρωση είναι συνεργατική – εφαρμόζεται στο επόμενο Yield (ή στην επόμενη γραμμή του σεναρίου μεταξύ εντολών).

7.3.3. Το μοντέλο αντικειμένων

Το ActiveDrawing επιστρέφει το τρέχον Drawing, το οποίο είναι το εργοστάσιο (factory) για όλα τα υπόλοιπα: δημιουργεί και επιστρέφει αντικείμενα Entity, Surface και Alignment. Τρία βοηθητικά αντικείμενα – Points, Profile και Elements – μεταφέρουν συλλογές.

globals
|
|-- flat creators ...... AddLine/AddCircle/AddArc/AddEllipse/
|                        AddRectangle/AddText/AddSurveyPoint/
|                        AddPolyline/AddHatch/AddTunnelSectionLine
|                        (return a handle STRING),
|                        CreateLayer/SetActiveLayer/ZoomExtents
|-- WriteLine / Cmd / Yield
|-- RegisterCommand / UnregisterCommand
|-- OnEvent / OffEvent
|-- dialogs ............ ShowMessage/Confirm/InputString/SelectFile
|-- NewPoints  --------> Points   (the array-free input builder)
|
`-- ActiveDrawing  ----> Drawing
                          |
                          |  create/returns
                          |
           +--------------+----------------+
           |              |                |
           v              v                v
        Entity         Surface          Alignment
        (geometry)     (TIN)            (horizontal)

        AddLine/Circle/Arc/Ellipse/Rectangle/Polyline/Text/
        SurveyPoint/Hatch/TunnelSectionLine     --> Entity
        CreateSurface / FindSurface / SurfaceAt --> Surface
        CreateAlignmentFromPolyline /
        FindAlignment / AlignmentAt             --> Alignment

        Surface.ProfileAlong  --> Profile  (Count + Station(i)/Z(i))
        Alignment.Elements    --> Elements (Count + Kind(i)/...)

Σχεδίαση χωρίς πίνακες. Το PascalScript χειρίζεται πτωχά τους δυναμικούς πίνακες, γι” αυτό το API της Pascal δεν δέχεται ούτε επιστρέφει ποτέ πίνακα. Η είσοδος σημείων γίνεται με έναν builder Points (NewPoints και έπειτα Add(x, y, z))· τα αποτελέσματα συλλογών επιστρέφονται ως αντικείμενα Profile και Elements που εκθέτουν ένα Count και μεθόδους δεικτοδότησης (Station(i) / Z(i) / Kind(i) …). Αυτή είναι η βασική διαφορά από την Python, η οποία χρησιμοποιεί εγγενείς λίστες και tuples.

Σημείωση

Μια flat καθολική συνάρτηση δημιουργίας (π.χ. AddCircle(...)) επιστρέφει τη συμβολοσειρά handle της νέας οντότητας, ενώ η αντικειμενοστραφής μέθοδος ActiveDrawing.AddCircle(...) επιστρέφει ένα αντικείμενο Entity που μπορείτε να συνεχίσετε να επεξεργάζεστε.

7.3.4. Αναφορά κλάσεων και καθολικών

7.3.4.1. Drawing

Λαμβάνεται από το ActiveDrawing. Το εργοστάσιο για οντότητες, επιφάνειες και χαράξεις.

Μέλος

Υπογραφή

Επιστρέφει

Περιγραφή

Name

ιδιότητα (μόνο ανάγνωση)

string

Όνομα σχεδίου.

ActiveLayer

ιδιότητα (ανάγνωση/εγγραφή)

string

Όνομα της τρέχουσας στρώσης.

AddLine

AddLine(x1, y1, z1, x2, y2, z2)

Entity

Γραμμή μεταξύ δύο σημείων.

AddCircle

AddCircle(cx, cy, cz, r)

Entity

Κύκλος, κέντρο + ακτίνα.

AddArc

AddArc(sx, sy, sz, mx, my, mz, ex, ey, ez)

Entity

Τόξο τριών σημείων.

AddEllipse

AddEllipse(cx, cy, cz, radx, rady, rot)

Entity

Έλλειψη με ημιάξονες και περιστροφή.

AddRectangle

AddRectangle(x1, y1, x2, y2)

Entity

Ορθογώνιο από απέναντι γωνίες.

AddText

AddText(x, y, z, s, h)

Entity

Κείμενο s στο σημείο, ύψους h.

AddSurveyPoint

AddSurveyPoint(x, y, z, num)

Entity

Σημείο τοπογραφίας με αριθμό num.

AddPolyline

AddPolyline(Pts, closed)

Entity

Πολυγραμμή μέσω μιας λίστας Points.

AddHatch

AddHatch(Pts, pattern, angle, scale)

Entity

Γραμμοσκίαση σε όριο Points.

AddTunnelSectionLine

AddTunnelSectionLine(Pts, closed)

Entity

Γραμμή διατομής σήραγγας.

CreateLayer

CreateLayer(n, color)

Boolean

Δημιουργεί στρώση (το color είναι δείκτης ACI).

EntityByHandle

EntityByHandle(h)

Entity

Αναζήτηση οντότητας μέσω handle (nil αν δεν υπάρχει).

ZoomExtents

ZoomExtents

–

Εστίαση στα όρια του σχεδίου.

CreateSurface

CreateSurface(name, Pts)

Surface

Δημιουργεί TIN από λίστα Points με (x, y, z).

FindSurface

FindSurface(name)

Surface

Αναζήτηση επιφάνειας με όνομα (nil αν δεν υπάρχει).

SurfaceCount

SurfaceCount

Integer

Πλήθος επιφανειών.

SurfaceAt

SurfaceAt(i)

Surface

Επιφάνεια με δείκτη που ξεκινά από το μηδέν.

CreateAlignmentFromPolyline

CreateAlignmentFromPolyline(polyHandle, radius, name)

Alignment

Δημιουργεί χάραξη από οντότητα πολυγραμμής.

CreateAlignmentFromPolylineZ

CreateAlignmentFromPolylineZ(polyHandle, radius, name, vcurveLen)

Alignment

Όπως το CreateAlignmentFromPolyline, αλλά δημιουργεί επιπλέον και τη μηκοτομή από τα υψόμετρα των κορυφών της πολυγραμμής (ένα PVI ανά κορυφή· το vcurveLen εφαρμόζεται στα ενδιάμεσα PVI, 0 = γωνιακή μηκοτομή).

FindAlignment

FindAlignment(name)

Alignment

Αναζήτηση χάραξης με όνομα (nil αν δεν υπάρχει).

AlignmentCount

AlignmentCount

Integer

Πλήθος χαράξεων.

AlignmentAt

AlignmentAt(i)

Alignment

Χάραξη με δείκτη που ξεκινά από το μηδέν.

7.3.4.2. Entity

Ένα μεμονωμένο αντικείμενο σχεδίου που επιστρέφεται από τις αντικειμενοστραφείς μεθόδους Add* ή από το EntityByHandle.

Μέλος

Υπογραφή

Επιστρέφει

Περιγραφή

Handle

ιδιότητα (μόνο ανάγνωση)

string

Μόνιμο handle.

TypeName

ιδιότητα (μόνο ανάγνωση)

string

'Line' | 'Circle' | 'Text' | …

Layer

ιδιότητα (ανάγνωση/εγγραφή)

string

Όνομα στρώσης.

Color

ιδιότητα (ανάγνωση/εγγραφή)

Integer

Δείκτης χρώματος ACI.

GetProperty

GetProperty(n)

string

Ανάγνωση τυποποιημένης ιδιότητας (π.χ. 'Radius' κύκλου).

SetProperty

SetProperty(n, v)

–

Εγγραφή τυποποιημένης ιδιότητας.

Delete

Delete

–

Διαγράφει την οντότητα· μεταγενέστερη πρόσβαση προστατεύεται και δεν κάνει τίποτα.

7.3.4.3. Surface

Μια επιφάνεια TIN που δημιουργείται με το Drawing.CreateSurface (ή εντοπίζεται μέσω FindSurface / SurfaceAt).

Μέλος

Υπογραφή

Επιστρέφει

Περιγραφή

Name

ιδιότητα (μόνο ανάγνωση)

string

Όνομα επιφάνειας.

Handle

ιδιότητα (μόνο ανάγνωση)

string

Μόνιμο handle.

ElevationAt

ElevationAt(x, y, out z)

Boolean

Παρεμβαλλόμενο Z στο z· False εκτός του TIN.

AddPoint

AddPoint(x, y, z)

–

Προσθέτει κορυφή και ανακατασκευάζει το TIN.

ProfileAlong

ProfileAlong(Pts)

Profile

Μηκοτομή κατά μήκος πολυγραμμής Points.

VolumeTo

VolumeTo(Other, cell, out cut, out fill)

Boolean

Προσεγγιστικός υπολογισμός ορύγματος/επιχώματος με κάνναβο· όρυγμα όπου η τρέχουσα επιφάνεια είναι πάνω από την Other.

7.3.4.4. Alignment

Μια οριζοντιογραφική χάραξη που δημιουργείται με το CreateAlignmentFromPolyline (ή εντοπίζεται μέσω FindAlignment / AlignmentAt).

Μέλος

Υπογραφή

Επιστρέφει

Περιγραφή

Name

ιδιότητα (μόνο ανάγνωση)

string

Όνομα χάραξης.

Handle

ιδιότητα (μόνο ανάγνωση)

string

Μόνιμο handle.

Length

ιδιότητα (μόνο ανάγνωση)

Double

Συνολικό μήκος.

StartStation

ιδιότητα (μόνο ανάγνωση)

Double

Αρχική χιλιομετρική θέση.

EndStation

ιδιότητα (μόνο ανάγνωση)

Double

Τελική χιλιομετρική θέση.

PointAtStation

PointAtStation(s, out x, out y, out z)

–

Παγκόσμιο σημείο στη χιλιομετρική θέση s.

DirectionAtStation

DirectionAtStation(s)

Double

Αζιμούθιο στη θέση s, σε ακτίνια.

ElevationAtStation

ElevationAtStation(s)

Double

Υψόμετρο μηκοτομής στη θέση s.

StationOffsetAt

StationOffsetAt(x, y, out station, out offset)

–

Πλησιέστερη χιλιομετρική θέση + πλευρική απόσταση (- αριστερά / + δεξιά).

Elements

Elements

Elements

Συλλογή γεωμετρικών στοιχείων.

7.3.4.5. Points, Profile, Elements

Τα βοηθητικά αντικείμενα χωρίς πίνακες. Το Points είναι ο builder εισόδου· τα Profile και Elements είναι συλλογές αποτελεσμάτων.

Αντικείμενο

Μέλος

Υπογραφή

Επιστρέφει

Points

Add

Add(x, y, z)

–

Points

Count

Count

Integer

Profile

Count

Count

Integer

Profile

Station

Station(i)

Double

Profile

Z

Z(i)

Double

Elements

Count

Count

Integer

Elements

Kind

Kind(i)

string

Elements

Length

Length(i)

Double

Elements

Radius

Radius(i)

Double

Elements

StartStation

StartStation(i)

Double

7.3.4.6. Καθολικές συναρτήσεις

Καλούνται χωρίς πρόθεμα. Οι flat συναρτήσεις δημιουργίας αντιστοιχούν στις μεθόδους του Drawing αλλά επιστρέφουν συμβολοσειρά handle αντί για αντικείμενο.

Μέλος

Υπογραφή

Επιστρέφει

Περιγραφή

ActiveDrawing

ActiveDrawing

Drawing

Το τρέχον σχέδιο.

NewPoints

NewPoints

Points

Ένας νέος, κενός builder Points.

WriteLine

WriteLine(s)

–

Τυπώνει μια γραμμή στη γραμμή εντολών.

Cmd

Cmd(s)

Boolean

Εκτελεί μια συμβολοσειρά γραμμής εντολών.

Yield

Yield

–

Ενημερώνει το UI· επιτρέπει ακύρωση με Esc.

AddLine

AddLine(x1, y1, z1, x2, y2, z2)

string

Flat γραμμή· επιστρέφει handle.

AddCircle

AddCircle(cx, cy, cz, r)

string

Flat κύκλος· επιστρέφει handle.

AddArc

AddArc(sx, sy, sz, mx, my, mz, ex, ey, ez)

string

Flat τόξο· επιστρέφει handle.

AddEllipse

AddEllipse(cx, cy, cz, radx, rady, rot)

string

Flat έλλειψη· επιστρέφει handle.

AddRectangle

AddRectangle(x1, y1, x2, y2)

string

Flat ορθογώνιο· επιστρέφει handle.

AddText

AddText(x, y, z, s, h)

string

Flat κείμενο· επιστρέφει handle.

AddSurveyPoint

AddSurveyPoint(x, y, z, num)

string

Flat σημείο τοπογραφίας· επιστρέφει handle.

AddPolyline

AddPolyline(Pts, closed)

string

Flat πολυγραμμή· επιστρέφει handle.

AddHatch

AddHatch(Pts, pattern, angle, scale)

string

Flat γραμμοσκίαση· επιστρέφει handle.

AddTunnelSectionLine

AddTunnelSectionLine(Pts, closed)

string

Flat γραμμή διατομής σήραγγας· επιστρέφει handle.

CreateLayer

CreateLayer(n, color)

Boolean

Δημιουργεί στρώση (color ACI).

SetActiveLayer

SetActiveLayer(n)

–

Ορίζει την τρέχουσα στρώση.

ZoomExtents

ZoomExtents

–

Εστίαση στα όρια του σχεδίου.

RegisterCommand

RegisterCommand(name, aliases, category, desc, procname)

–

Καταχωρίζει εντολή συνδεδεμένη με procedure του σεναρίου.

UnregisterCommand

UnregisterCommand(name)

–

Αφαιρεί μια καταχωρισμένη εντολή.

OnEvent

OnEvent(eventName, procname)

–

Συνδέει χειριστή συμβάντος μέσω ονόματος procedure.

OffEvent

OffEvent(eventName, procname)

–

Αποσυνδέει χειριστή συμβάντος.

7.3.5. Εντολές και συμβάντα

7.3.5.1. Προσαρμοσμένες εντολές

Το RegisterCommand συνδέει μια νέα εντολή του IQcad με μια procedure του σεναρίου μέσω ονόματος. Φορτώστε το σενάριο μόνιμα με PASLOAD (ή τοποθετήστε το στον φάκελο αυτόματης φόρτωσης) και η εντολή μπορεί να πληκτρολογηθεί στην προτροπή όπως κάθε ενσωματωμένη.

program ext;
procedure DoGrid(arg: string);
begin
  { το arg φτάνει ως συμβολοσειρά -- αναλύστε το μόνοι σας }
  AddCircle(0, 0, 0, StrToFloatDef(arg, 1.0));
end;
begin
  RegisterCommand('PASGRID', 'PG', 'Tools', 'Draw a grid', 'DoGrid');
end.

Προειδοποίηση

Τα ορίσματα εντολών φτάνουν ως συμβολοσειρά. Αναλύστε τα μόνοι σας με StrToFloatDef / StrToIntDef.

Αφαιρέστε μια καταχώριση με UnregisterCommand('PASGRID').

7.3.5.2. Συμβάντα

Το OnEvent συνδέει μια procedure χειριστή (μέσω ονόματος) με ένα συμβάν του σχεδίου.

Όνομα συμβάντος

Υπογραφή χειριστή

Ενεργοποιείται όταν

'entity_created'

procedure(handle: string)

Δημιουργείται μια οντότητα.

'entity_deleted'

procedure(handle: string)

Διαγράφεται μια οντότητα.

'selection_changed'

procedure (χωρίς ορίσματα)

Αλλάζει η επιλογή.

Αποσυνδέστε έναν χειριστή με OffEvent(eventName, procname).

Σημείωση

Οι χειριστές εκτελούνται σύγχρονα στο νήμα του GUI. Μια εξαίρεση μέσα σε χειριστή καταγράφεται στη γραμμή εντολών και δεν είναι μοιραία. Ένας χειριστής που δημιουργεί ο ίδιος οντότητες ενεργοποιεί ξανά το entity_created και μπορεί να προκαλέσει αναδρομή – προστατευτείτε με μια boolean μεταβλητή επιπέδου module (δείτε samples\pascal\03_events.pas).

7.3.6. Διάλογοι

Τέσσερις καθολικές συναρτήσεις διαλόγων – κοινές με τον host Python – ζητούν είσοδο από τον χρήστη. Όταν εκτελούνται χωρίς GUI (headless), επιστρέφουν ασφαλείς προεπιλογές ώστε ένα σενάριο χωρίς επίβλεψη να μην μπλοκάρει ποτέ.

Συνάρτηση

Υπογραφή

Προεπιλογή χωρίς GUI

ShowMessage

ShowMessage(s)

καμία ενέργεια

Confirm

Confirm(s): Boolean

False

InputString

InputString(prompt, def: string; out v: string): Boolean

False (v = def)

SelectFile

SelectFile(title, filter: string; save: Boolean): string

''

Το filter του SelectFile είναι ένα ζεύγος Caption|Mask διαχωρισμένο με κάθετο (π.χ. 'CSV files|*.csv')· το save επιλέγει διάλογο ανοίγματος ή αποθήκευσης.

7.3.7. Διαθέσιμη RTL

Ο host καταχωρίζει ένα υποσύνολο της RTL της Pascal μαζί με μερικές προσθήκες. Παρέχονται μετατροπές αριθμών κινητής υποδιαστολής ανεξάρτητες από τις τοπικές ρυθμίσεις, ώστε τα σενάρια να συμπεριφέρονται ίδια ανεξάρτητα από το διαχωριστικό δεκαδικών του συστήματος.

  • Συμβολοσειρές: Copy, Pos, Length, UpperCase, LowerCase, Trim.

  • Αριθμοί: IntToStr, StrToInt, StrToIntDef, FloatToStr, StrToFloat, StrToFloatDef (οι συναρτήσεις κινητής υποδιαστολής είναι ανεξάρτητες από τις τοπικές ρυθμίσεις – πάντα . ως υποδιαστολή).

  • Μαθηματικά: Sin, Cos, Sqrt, Round, Trunc, Abs, Pi, ArcTan, Power.

  • Μορφοποίηση: FmtFloat(v: Double; decimals: Integer): string – μορφοποιητής σταθερού πλήθους δεκαδικών, ανεξάρτητος από τις τοπικές ρυθμίσεις.

Προειδοποίηση

Το Format (η παραλλαγή με array of const) δεν είναι διαθέσιμο. Συνθέστε συμβολοσειρές με FmtFloat + IntToStr + συνένωση, π.χ. WriteLine('STA ' + FmtFloat(s, 1) + '  Z=' + FmtFloat(z, 3)).

7.3.8. Παραδείγματα

Επτά πλήρη σενάρια συνοδεύουν το IQcad στο samples\pascal\:

  • samples\pascal\01_primitives.pas – γεωμετρία, στρώσεις, οι αντικειμενοστραφείς έναντι των flat συναρτήσεων δημιουργίας, Points για πολυγραμμή + γραμμοσκίαση.

  • samples\pascal\02_command.pas – καταχώριση προσαρμοσμένης εντολής.

  • samples\pascal\03_events.pas – σύνδεση χειριστών συμβάντων.

  • samples\pascal\04_surface.pas – επιφάνειες TIN: δημιουργία, ερώτημα, μηκοτομή, όγκος.

  • samples\pascal\05_alignment.pas – χαράξεις από πολυγραμμή.

  • samples\pascal\06_civil_workflow.pas – χιλιομέτρηση κατά μήκος χάραξης με δειγματοληψία επιφάνειας (το κορυφαίο παράδειγμα).

  • samples\pascal\07_dialogs.pas – οι τέσσερις διάλογοι αλληλεπίδρασης με τον χρήστη.

7.3.8.1. Επιφάνειες

Δημιουργία TIN από αρχικά σημεία, παρεμβολή, λήψη μηκοτομής και έπειτα σύγκριση δύο επιφανειών κατ” όγκο (04_surface.pas):

program surface;
var
  d: Drawing;
  pts, line: Points;
  eg, fg: Surface;
  prof: Profile;
  z, cut, fill: Double;
  i: Integer;
begin
  d := ActiveDrawing;

  pts := NewPoints;
  pts.Add(0, 0, 10.0);  pts.Add(50, 0, 11.0);  pts.Add(50, 40, 12.5);
  pts.Add(0, 40, 10.5); pts.Add(25, 20, 11.2);
  eg := d.CreateSurface('EG', pts);

  if eg.ElevationAt(25, 20, z) then       { False εκτός του TIN }
    WriteLine('Z at (25,20) = ' + FmtFloat(z, 3));

  eg.AddPoint(25, 40, 11.8);              { ανακατασκευάζει το TIN }

  line := NewPoints;
  line.Add(0, 20, 0); line.Add(50, 20, 0);
  prof := eg.ProfileAlong(line);
  for i := 0 to prof.Count - 1 do
    WriteLine('STA ' + FmtFloat(prof.Station(i), 3) +
              '  Z ' + FmtFloat(prof.Z(i), 3));

  pts := NewPoints;
  pts.Add(0, 0, 11.0);  pts.Add(50, 0, 12.0);  pts.Add(50, 40, 13.5);
  pts.Add(0, 40, 11.5); pts.Add(25, 20, 12.2);
  fg := d.CreateSurface('FG', pts);
  if eg.VolumeTo(fg, 1.0, cut, fill) then
    WriteLine('cut=' + FmtFloat(cut, 2) + '  fill=' + FmtFloat(fill, 2));
end.

7.3.8.2. Χαράξεις

Δημιουργία χάραξης από πολυγραμμή (απαιτείται ακτίνα στρογγύλευσης για 3 ή περισσότερες κορυφές) και έπειτα ερωτήματα σε αυτήν (05_alignment.pas):

program alignment;
var
  d: Drawing;
  pts: Points;
  e: Entity;
  al: Alignment;
  el: Elements;
  x, y, z, dir, st, off: Double;
  i: Integer;
begin
  d := ActiveDrawing;

  pts := NewPoints;
  pts.Add(0, 0, 0); pts.Add(100, 0, 0);
  pts.Add(100, 50, 0); pts.Add(160, 50, 0);
  e := d.AddPolyline(pts, False);

  al := d.CreateAlignmentFromPolyline(e.Handle, 20.0, 'CL-1');
  WriteLine('len=' + FmtFloat(al.Length, 3) +
            '  STA ' + FmtFloat(al.StartStation, 3) +
            '..' + FmtFloat(al.EndStation, 3));

  al.PointAtStation(50.0, x, y, z);
  dir := al.DirectionAtStation(50.0);             { ακτίνια }
  al.StationOffsetAt(50.0, 5.0, st, off);         { απόσταση - αριστερά / + δεξιά }

  el := al.Elements;
  for i := 0 to el.Count - 1 do
    WriteLine(el.Kind(i) +
              ' len=' + FmtFloat(el.Length(i), 3) +
              ' R=' + FmtFloat(el.Radius(i), 3));
end.

7.3.8.3. Συνδυασμένη ροή εργασιών πολιτικού μηχανικού

Το κορυφαίο παράδειγμα: βηματική χιλιομέτρηση κατά μήκος χάραξης με δειγματοληψία της επιφάνειας εδάφους σε κάθε χιλιομετρική θέση (06_civil_workflow.pas):

program civil_workflow;
var
  d: Drawing;
  pts: Points;
  e: Entity;
  surf: Surface;
  al: Alignment;
  step, s, x, y, z, gz: Double;
begin
  d := ActiveDrawing;

  pts := NewPoints;
  pts.Add(-20, -20, 10.0); pts.Add(180, -20, 14.0); pts.Add(180, 80, 16.0);
  pts.Add(-20, 80, 11.0);  pts.Add(80, 25, 13.0);
  surf := d.CreateSurface('EG', pts);

  pts := NewPoints;
  pts.Add(0, 0, 0); pts.Add(100, 0, 0);
  pts.Add(100, 50, 0); pts.Add(160, 50, 0);
  e := d.AddPolyline(pts, False);
  al := d.CreateAlignmentFromPolyline(e.Handle, 20.0, 'CL-1');

  step := 10.0;
  s := al.StartStation;
  while s <= al.EndStation + 1e-6 do
  begin
    al.PointAtStation(s, x, y, z);
    if surf.ElevationAt(x, y, gz) then     { False εκτός του TIN }
      WriteLine('STA ' + FmtFloat(s, 1) + '  surf=' + FmtFloat(gz, 3))
    else
      WriteLine('STA ' + FmtFloat(s, 1) + '  surf=(outside TIN)');
    s := s + step;
    Yield;                                 { διατήρηση απόκρισης / δυνατότητα Esc }
  end;
end.

7.3.9. Διάλογοι και πλαίσια μηνυμάτων

Τα σενάρια Pascal μπορούν να εμφανίσουν διάλογο παραμέτρων ή πλαίσιο μηνύματος που κατασκευάζει ο host — το ίδιο UI που χρησιμοποιεί το SDK προσθέτων.

Το CreateDialog(title): TScriptDialog επιστρέφει έναν διάλογο· περιγράψτε τα πεδία, καλέστε Execute και έπειτα διαβάστε τις τιμές:

var
  dlg: TScriptDialog;
  shape: Integer; size: Double; layer: string; col: Integer; filled: Boolean;
begin
  dlg := CreateDialog('Draw a shape');
  dlg.AddChoice('shape', 'Shape', 'Rectangle'#9'Circle', 0);  { το TAB διαχωρίζει τις επιλογές }
  dlg.AddFloat ('size',  'Size (m)', 10, 0, 0, 2);            { Min=Max=0 → χωρίς όρια }
  dlg.AddText  ('layer', 'Layer name', 'SHAPES');
  dlg.AddColor ('color', 'Color', $00B400);                   { 0x00BBGGRR }
  dlg.AddBool  ('filled','Filled?', False);
  if dlg.Execute then
  begin
    shape  := dlg.GetChoice('shape');   { δείκτης επιλογής }
    size   := dlg.GetFloat('size');
    layer  := dlg.GetText('layer');
    col    := dlg.GetColor('color');
    filled := dlg.GetBool('filled');
  end;
end.

Builders: AddText, AddMultiline, AddInt(…, Min, Max), AddFloat(…, Min, Max, Decimals), AddBool, AddChoice(Key, Caption, Options, DefaultIndex), AddFile(…, Filter, SaveDlg), AddFolder, AddColor. Getters: GetText (επίσης το κείμενο της επιλεγμένης επιλογής), GetInt, GetFloat, GetBool, GetChoice (δείκτης), GetColor. Το Execute επιστρέφει False αν ο χρήστης ακυρώσει.

Το MessageBox(Text, Caption: string; Buttons, Icon: Integer): Integer εμφανίζει πλαίσιο μηνύματος και επιστρέφει το κουμπί που πατήθηκε. Ακέραιοι κωδικοί — κουμπιά: 0 OK, 1 OK/Cancel, 2 Yes/No, 3 Yes/No/Cancel· εικονίδια: 0 κανένα, 1 πληροφορία, 2 προειδοποίηση, 3 σφάλμα, 4 ερώτηση· αποτελέσματα: 0 OK, 1 Cancel, 2 Yes, 3 No (ένα πλαίσιο που κλείνει χωρίς επιλογή επιστρέφει 1):

if MessageBox('Delete selection?', 'Confirm', 2, 4) = 2 then  { YesNo, ερώτηση → Yes }
  WriteLn('confirmed');

7.3.10. Ζωντανές φόρμες

Μια ζωντανή φόρμα (live form) είναι ένα non-modal παράθυρο εργαλείου, που ανήκει στον host και παραμένει ανοικτό: κατασκευάζετε στοιχεία ελέγχου, κρατάτε αναφορές σε αυτά, τα τροποποιείτε κατά την εκτέλεση και αντιδράτε στον χρήστη μέσω χειριστών συμβάντων. Είναι η πλευρά σεναρίων των ζωντανών παραθύρων εργαλείων του SDK προσθέτων.

Το CreateForm(title): TScriptForm επιστρέφει μια ζωντανή φόρμα. Οι builders Add* της (AddButton, AddLabel, AddText, AddMultiline, AddInt, AddFloat, AddBool, AddChoice, AddColor, AddFile, AddFolder, AddList) επιστρέφουν ο καθένας ένα TScriptControl με τυποποιημένους accessors Get* / Set* και λειτουργίες λίστας· η φόρμα διαθέτει επίσης BeginRow / EndRow, FindControl, Show / Hide / Close / IsVisible / SetTitle. Αναθέστε το όνομα μιας procedure του σεναρίου στα OnButtonClicked / OnValueChanged / OnFormClosed και ο host θα την καλέσει:

var frm: TScriptForm;

procedure HandleClick(const Key: string);
var n: Integer;
begin
  if Key = 'add' then
  begin
    n := frm.FindControl('n').GetInt;
    frm.FindControl('log').AppendLine('Added: ' + IntToStr(n));
    frm.FindControl('status').SetText('Last added: ' + IntToStr(n));
  end;
end;

begin
  frm := CreateForm('Form demo');
  frm.AddLabel('status', 'Click Add to append a value');
  frm.AddInt('n', 'Value', 1, 0, 1000);
  frm.AddButton('add', 'Add');
  frm.AddList('log', 'Log');
  frm.OnButtonClicked := 'HandleClick';   { όνομα της procedure του σεναρίου }
  frm.Show;
end.

Το CreatePanel(title): TScriptForm είναι ίδιο με το CreateForm αλλά προσαρτά το πάνελ στο κύριο παράθυρο — εμφανίζεται ως καρτέλα στη δεξιά λωρίδα προσάρτησης αντί για αιωρούμενο παράθυρο. Οι builders Add* και οι χειριστές συμβάντων On* είναι ακριβώς οι ίδιοι· διαφέρει μόνο ο περιέκτης:

frm := CreatePanel('Form demo');   { προσαρτημένο δίδυμο του CreateForm }

7.3.11. Ribbon και μενού

Τα AddRibbonButton(group, command, caption, hint, iconfile, large): Boolean και AddMenuItem(submenu, command, caption): Boolean προσθέτουν στοιχεία GUI που εκτελούν μια καταχωρισμένη εντολή — ένα κουμπί στην καρτέλα ribbon Plugins και ένα στοιχείο στο μενού Plugins. Τα σενάρια εμφανίζονται κάτω από μία ενιαία ομάδα/υπομενού Scripts· το iconfile είναι απόλυτη διαδρομή προς αρχείο PNG (κενό για γενικό εικονίδιο). Δείτε Συνεισφορές σε κορδέλα και μενού.

AddRibbonButton('Demo', 'GREET', 'Greet', 'Say hello', '', True);
AddMenuItem('Demo', 'GREET', 'Greet');

7.3.12. Περιορισμοί και συμβουλές

  • Το PASEVAL δέχεται μία έκφραση. Αποτιμά μία έκφραση Pascal και τυπώνει την τιμή της· δεν προορίζεται για εντολές (statements).

  • Χωρίς ``Format`` / ``array of const``. Συνθέστε συμβολοσειρές με FmtFloat + IntToStr + συνένωση.

  • API χωρίς πίνακες. Περάστε σημεία μέσω builder Points· διαβάστε αποτελέσματα συλλογών μέσω Count + δεικτών των Profile / Elements. Δεν υπάρχουν παράμετροι ή αποτελέσματα τύπου πίνακα.

  • Ακτίνα στρογγύλευσης χάραξης. Το CreateAlignmentFromPolyline με radius = 0 (η προεπιλογή) δημιουργεί ευθύγραμμες εφαπτόμενες μέσω κάθε κορυφής, ακόμη και για πολυγραμμές με 3 ή περισσότερες κορυφές. Δώστε μη μηδενική ακτίνα (τουλάχιστον 0.01) μόνο αν θέλετε οι ενδιάμεσες γωνίες να στρογγυλευτούν σε τόξα.

  • Το ``ElevationAt`` επιστρέφει False εκτός του TIN. Ελέγχετε πάντα το αποτέλεσμα πριν χρησιμοποιήσετε την παράμετρο εξόδου.

  • Πρόσημο πλευρικής απόστασης. Το StationOffsetAt επιστρέφει πλευρική απόσταση που είναι αρνητική προς τα αριστερά και θετική προς τα δεξιά της διεύθυνσης της χάραξης.

  • Τα ορίσματα εντολών είναι συμβολοσειρές. Αναλύστε τα με StrToFloatDef / StrToIntDef.

  • Περιορισμένη κάλυψη συμβάντων. Υπάρχουν μόνο τα entity_created, entity_deleted και selection_changed· δεν υπάρχει ακόμη on_entity_modified ούτε συμβάντα κύκλου ζωής σχεδίου ή εντολών.

  • Χωρίς εκτέλεση στο παρασκήνιο / ασύγχρονη εκτέλεση. Τα σενάρια εκτελούνται στο νήμα του GUI· καλείτε Yield ώστε οι μακροσκελείς βρόχοι να παραμένουν αποκρίσιμοι και να ακυρώνονται με Esc.