1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189 |
- //
- // The graphics engine GXScene
- //
- unit GXS.Coordinates;
- (*
- Coordinate related classes and functions.
- The registered classes are:
- [TgxCoordinates2, TgxCoordinates3, TgxCoordinates4]
- *)
- interface
- {$I Stage.Defines.inc}
- uses
- System.Math,
- System.Classes,
- System.SysUtils,
- Stage.VectorGeometry,
- Stage.VectorTypes,
- GXS.BaseClasses;
- type
- (* Identifies the type of data stored within a TgxCustomCoordinates.
- csPoint2D : a simple 2D point (Z=0, W=0)
- csPoint : a point (W=1)
- csVector : a vector (W=0)
- csUnknown : no constraint *)
- TgxCoordinatesStyle = (csPoint2D, csPoint, csVector, csUnknown);
- (* Stores any homogeneous vector.
- This class is basicly a container for a TGLVector, allowing proper use of
- property editors and editing in the IDE. Vector/Coordinates
- manipulation methods are only minimal.
- Handles dynamic default values to save resource file space. *)
- TgxCustomCoordinates = class(TgxUpdateAbleObject)
- private
- FCoords: TGLVector;
- FStyle: TgxCoordinatesStyle; // NOT Persistent
- FPDefaultCoords: PGLVector;
- procedure SetAsPoint2D(const Value: TVector2f);
- procedure SetAsVector(const Value: TGLVector);
- procedure SetAsAffineVector(const Value: TAffineVector);
- function GetAsAffineVector: TAffineVector; inline;
- function GetAsPoint2D: TVector2f;
- function GetAsString: String;
- function GetCoordinate(const AIndex: Integer): Single; inline;
- procedure SetCoordinate(const AIndex: Integer; const AValue: Single); inline;
- function GetDirectCoordinate(const Index: Integer): Single; inline;
- procedure SetDirectCoordinate(const Index: Integer; const AValue: Single);
- protected
- procedure SetDirectVector(const V: TGLVector); inline;
- procedure DefineProperties(Filer: TFiler); override;
- procedure ReadData(Stream: TStream);
- procedure WriteData(Stream: TStream);
- public
- constructor CreateInitialized(AOwner: TPersistent; const AValue: TGLVector;
- const AStyle: TgxCoordinatesStyle = CsUnknown);
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- procedure WriteToFiler(Writer: TWriter);
- procedure ReadFromFiler(Reader: TReader);
- procedure Initialize(const Value: TGLVector);
- procedure NotifyChange(Sender: TObject); override;
- (* Identifies the coordinates styles.
- The property is NOT persistent, csUnknown by default, and should be
- managed by owner object only (internally).
- It is used by the TgxCustomCoordinates for internal "assertion" checks
- to detect "misuses" or "misunderstandings" of what the homogeneous
- coordinates system implies. *)
- property Style: TgxCoordinatesStyle read FStyle write FStyle;
- procedure Translate(const TranslationVector: TGLVector); overload;
- procedure Translate(const TranslationVector: TAffineVector); overload;
- procedure AddScaledVector(const Factor: Single; const TranslationVector: TGLVector); overload;
- procedure AddScaledVector(const Factor: Single; const TranslationVector: TAffineVector); overload;
- procedure Rotate(const AnAxis: TAffineVector; AnAngle: Single); overload;
- procedure Rotate(const AnAxis: TGLVector; AnAngle: Single); overload;
- procedure Normalize; inline;
- procedure Invert;
- procedure Scale(Factor: Single);
- function VectorLength: Single;
- function VectorNorm: Single;
- function MaxXYZ: Single;
- function Equals(const AVector: TGLVector): Boolean; reintroduce;
- procedure SetVector(const X, Y: Single; Z: Single = 0); overload;
- procedure SetVector(const X, Y, Z, W: Single); overload;
- procedure SetVector(const V: TAffineVector); overload;
- procedure SetVector(const V: TGLVector); overload;
- procedure SetPoint(const X, Y, Z: Single); overload;
- procedure SetPoint(const V: TAffineVector); overload;
- procedure SetPoint(const V: TGLVector); overload;
- procedure SetPoint2D(const X, Y: Single); overload;
- procedure SetPoint2D(const Vector: TAffineVector); overload;
- procedure SetPoint2D(const Vector: TGLVector); overload;
- procedure SetPoint2D(const Vector: TVector2f); overload;
- procedure SetToZero;
- function AsAddress: PSingle; inline;
- (* The coordinates viewed as a vector.
- Assigning a value to this property will trigger notification events,
- if you don't want so, use DirectVector instead. *)
- property AsVector: TGLVector read FCoords write SetAsVector;
- (* The coordinates viewed as an affine vector.
- Assigning a value to this property will trigger notification events,
- if you don't want so, use DirectVector instead.
- The W component is automatically adjustes depending on style. *)
- property AsAffineVector: TAffineVector read GetAsAffineVector write SetAsAffineVector;
- (* The coordinates viewed as a 2D point.
- Assigning a value to this property will trigger notification events,
- if you don't want so, use DirectVector instead. *)
- property AsPoint2D: TVector2f read GetAsPoint2D write SetAsPoint2D;
- property X: Single index 0 read GetCoordinate write SetCoordinate;
- property Y: Single index 1 read GetCoordinate write SetCoordinate;
- property Z: Single index 2 read GetCoordinate write SetCoordinate;
- property W: Single index 3 read GetCoordinate write SetCoordinate;
- property Coordinate[const AIndex: Integer]: Single read GetCoordinate write SetCoordinate; default;
- // The coordinates, in-between brackets, separated by semi-colons.
- property AsString: String read GetAsString;
- // Similar to AsVector but does not trigger notification events
- property DirectVector: TGLVector read FCoords write SetDirectVector;
- property DirectX: Single index 0 read GetDirectCoordinate write SetDirectCoordinate;
- property DirectY: Single index 1 read GetDirectCoordinate write SetDirectCoordinate;
- property DirectZ: Single index 2 read GetDirectCoordinate write SetDirectCoordinate;
- property DirectW: Single index 3 read GetDirectCoordinate write SetDirectCoordinate;
- end;
- // A TgxCustomCoordinates that publishes X, Y properties.
- TgxCoordinates2 = class(TgxCustomCoordinates)
- published
- property X stored False;
- property Y stored False;
- end;
- // A TgxCustomCoordinates that publishes X, Y, Z properties.
- TgxCoordinates3 = class(TgxCustomCoordinates)
- published
- property X stored False;
- property Y stored False;
- property Z stored False;
- end;
- // A TgxCustomCoordinates that publishes X, Y, Z, W properties.
- TgxCoordinates4 = class(TgxCustomCoordinates)
- published
- property X stored False;
- property Y stored False;
- property Z stored False;
- property W stored False;
- end;
- TgxCoordinates = TgxCoordinates3;
- (* Actually Sender should be TgxCustomCoordinates, but that would require
- changes in a some other units and some other projects that use
- TgxCoordinatesUpdateAbleComponent *)
- IgxCoordinatesUpdateAble = interface(IInterface)
- ['{ACB98D20-8905-43A7-AFA5-225CF5FA6FF5}']
- procedure CoordinateChanged(Sender: TgxCustomCoordinates);
- end;
- TgxCoordinatesUpdateAbleComponent = class(TgxUpdateAbleComponent, IgxCoordinatesUpdateAble)
- public
- procedure CoordinateChanged(Sender: TgxCustomCoordinates); virtual; abstract;
- end;
- (* Calculates the barycentric coordinates for the point p on the triangle
- defined by the vertices v1, v2 and v3. That is, solves
- p = u * v1 + v * v2 + (1-u-v) * v3
- for u,v.
- Returns true if the point is inside the triangle, false otherwise.
- NOTE: This function assumes that the point lies on the plane defined by the triangle.
- If this is not the case, the function will not work correctly!
- https://mathworld.wolfram.com/BarycentricCoordinates.html *)
- function BarycentricCoordinates(const V1, V2, V3, p: TAffineVector; var u, V: Single): Boolean;
- //-------------------- Conversions of Coordinates --------------------
- (*
- Helper functions to convert between different three dimensional coordinate
- systems. Room for optimisations.
- *)
- (* Convert Cylindrical to Cartesian [single] with no checks, theta in rad
- Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
- procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single); overload;
- (* Convert Cylindrical to Cartesian with no checks. Double version, theta in rads
- Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
- procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double); overload;
- (* Convert Cylindrical to Cartesian with checks. [single], theta in rad
- ierr: [0] = ok,
- [1] = r out of bounds. Acceptable r: [0,inf)
- [2] = theta out of bounds. Acceptable theta: [0,2pi)
- [3] = z1 out of bounds. Acceptable z1 : (-inf,inf)
- Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
- procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single;
- var ierr: integer); overload;
- (* Convert Cylindrical to Cartesian with checks. [double], theta in rad
- ierr: [0] = ok,
- [1] = r out of bounds. Acceptable r: [0,inf)
- [2] = theta out of bounds. Acceptable theta: [0,2pi)
- [3] = z1 out of bounds. Acceptable z1 : (-inf,inf)
- Ref: http://mathworld.wolfram.com/CylindricalCoordinates.html *)
- procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double;
- var ierr: integer); overload;
- (* Convert Cartesian to Cylindrical no checks. Single *)
- procedure Cartesian_Cylindrical(const x, y, z1: single; var r, theta, z: single); overload;
- (* Convert Cartesian to Cylindrical no checks. Duoble *)
- procedure Cartesian_Cylindrical(const x, y, z1: double; var r, theta, z: double); overload;
- (* Convert Spherical to Cartesian with no checks. [single] theta,phi in rads
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
- procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single); overload;
- (* Convert Spherical to Cartesian with no checks. Double version. theta,phi in rads *)
- procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double); overload;
- (* Convert Spherical to Cartesian [single] (with error check).theta,phi in rad
- ierr: [0] = ok,
- [1] = r out of bounds
- [2] = theta out of bounds
- [3] = phi out of bounds
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
- procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single;
- var ierr: integer); overload;
- // Convert spherical to cartesian [double] (with error check).theta,phi in rad
- procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double;
- var ierr: integer); overload;
- (* Convert Cartesian to Spherical, no checks, single
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html
- NB: Could be optimised by using jclmath.pas unit *)
- procedure Cartesian_Spherical(const x, y, z: single; var r, theta, phi: single); overload;
- (* Convert Cartesian to Spherical, no checks, single
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html
- NB: Could be optimised by using fastmath.pas unit *)
- procedure Cartesian_Spherical(const v: TAffineVector; var r, theta, phi: single); overload;
- (* convert Cartesian to Spherical, no checks, double
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html
- NB: Could be optimised by using jclmath.pas unit? *)
- procedure Cartesian_Spherical(const x, y, z: double; var r, theta, phi: double); overload;
- (* Convert Prolate-Spheroidal to Cartesian with no checks. [single] eta, phi in rad
- A system of curvilinear coordinates in which two sets of coordinate surfaces are
- obtained by revolving the curves of the elliptic cylindrical coordinates about
- the x-axis, which is relabeled the z-axis. The third set of coordinates
- consists of planes passing through this axis.
- The coordinate system is parameterised by parameter a.
- A default value of a=1 is suggesed:
- Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single); overload;
- (* Convert Prolate-Spheroidal to Cartesian [double] eta,phi in rad
- A system of curvilinear coordinates in which two sets of coordinate surfaces are
- obtained by revolving the curves of the elliptic cylindrical coordinates about
- the x-axis, which is relabeled the z-axis. The third set of coordinates
- consists of planes passing through this axis.
- The coordinate system is parameterised by parameter a. A default value of a=1 is
- suggesed: Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double); overload;
- (* Convert Prolate-Spheroidal to Cartesian [single](with error check). eta,phi in rad
- ierr: [0] = ok,
- [1] = xi out of bounds. Acceptable xi: [0,inf)
- [2] = eta out of bounds. Acceptable eta: [0,pi]
- [3] = phi out of bounds. Acceptable phi: [0,2pi)
- Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single; var ierr: integer); overload;
- (* Convert Prolate-Spheroidal to Cartesian [double](with error check). eta,phi in rad
- ierr: [0] = ok,
- [1] = xi out of bounds. Acceptable xi: [0,inf)
- [2] = eta out of bounds. Acceptable eta: [0,pi]
- [3] = phi out of bounds. Acceptable phi: [0,2pi)
- Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double; var ierr: integer); overload;
- // Convert Oblate-Spheroidal to Cartesian. [Single] eta, phi in rad
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single); overload;
- // Convert Oblate-Spheroidal to Cartesian. [Double] eta, phi in rad
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double); overload;
- // Convert Oblate-Spheroidal to Cartesian (with error check). eta,phi in rad
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single; var ierr: integer); overload;
- (* Convert Oblate-Spheroidal to Cartesian with checks. [Double] eta,phi in rad
- ierr: [0] = ok,
- [1] = xi out of bounds. Acceptable xi: [0,inf)
- [2] = eta out of bounds. Acceptable eta: [-0.5*pi,0.5*pi]
- [3] = phi out of bounds. Acceptable phi: [0,2*pi)
- Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double; var ierr: integer); overload;
- // Convert Bipolar to Cartesian. u in rad
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
- var x, y, z: single); overload;
- (* Convert BiPolarCylindrical to Cartesian with no checks. Double, u in rad
- http://mathworld.wolfram.com/BipolarCylindricalCoordinates.html *)
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
- var x, y, z: double); overload;
- // Convert Bipolar to Cartesian (with error check). u in rad
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
- var x, y, z: single; var ierr: integer); overload;
- (* Convert Oblate-Spheroidal to Cartesian with checks. Double, u in rad
- ierr: [0] = ok,
- [1] = u out of bounds. Acceptable u: [0,2*pi)
- [2] = v out of bounds. Acceptable v: (-inf,inf)
- [3] = z1 out of bounds. Acceptable z1: (-inf,inf)
- Ref: https://mathworld.wolfram.com/BipolarCylindricalCoordinates.html *)
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
- var x, y, z: double; var ierr: integer); overload;
- var
- (* Specifies if TgxCustomCoordinates should allocate memory for
- their default values (ie. design-time) or not (run-time) *)
- VUseDefaultCoordinateSets: Boolean = False;
- implementation //-------------------------------------------------------------
- const
- csVectorHelp = 'When getting assertions here use the SetPoint procedure';
- csPointHelp = 'When getting assertions here use the SetVector procedure';
- csPoint2DHelp = 'When getting assertions here use one of the SetVector or SetPoint procedures';
- // ------------------
- // ------------------ TgxCustomCoordinates ------------------
- // ------------------
- constructor TgxCustomCoordinates.CreateInitialized(AOwner: TPersistent;
- const AValue: TGLVector; const AStyle: TgxCoordinatesStyle = CsUnknown);
- begin
- Create(AOwner);
- Initialize(AValue);
- FStyle := AStyle;
- end;
- destructor TgxCustomCoordinates.Destroy;
- begin
- if Assigned(FPDefaultCoords) then
- Dispose(FPDefaultCoords);
- inherited;
- end;
- procedure TgxCustomCoordinates.Initialize(const Value: TGLVector);
- begin
- FCoords := Value;
- if VUseDefaultCoordinateSets then
- begin
- if not Assigned(FPDefaultCoords) then
- New(FPDefaultCoords);
- FPDefaultCoords^ := Value;
- end;
- end;
- procedure TgxCustomCoordinates.Assign(Source: TPersistent);
- begin
- if Source is TgxCustomCoordinates then
- FCoords := TgxCustomCoordinates(Source).FCoords
- else
- inherited;
- end;
- procedure TgxCustomCoordinates.WriteToFiler(Writer: TWriter);
- var
- WriteCoords: Boolean;
- begin
- with Writer do
- begin
- WriteInteger(0); // Archive Version 0
- if VUseDefaultCoordinateSets then
- WriteCoords := not VectorEquals(FPDefaultCoords^, FCoords)
- else
- WriteCoords := True;
- WriteBoolean(WriteCoords);
- if WriteCoords then
- Write(FCoords.X, SizeOf(FCoords));
- end;
- end;
- procedure TgxCustomCoordinates.ReadFromFiler(Reader: TReader);
- var
- N: Integer;
- begin
- with Reader do
- begin
- ReadInteger; // Ignore ArchiveVersion
- if ReadBoolean then
- begin
- N := SizeOf(FCoords);
- Assert(N = 4 * SizeOf(Single));
- Read(FCoords.X, N);
- end
- else if Assigned(FPDefaultCoords) then
- FCoords := FPDefaultCoords^;
- end;
- end;
- procedure TgxCustomCoordinates.DefineProperties(Filer: TFiler);
- begin
- inherited;
- Filer.DefineBinaryProperty('Coordinates', ReadData, WriteData,
- not(Assigned(FPDefaultCoords) and VectorEquals(FPDefaultCoords^, FCoords)));
- end;
- procedure TgxCustomCoordinates.ReadData(Stream: TStream);
- begin
- Stream.Read(FCoords, SizeOf(FCoords));
- end;
- procedure TgxCustomCoordinates.WriteData(Stream: TStream);
- begin
- Stream.Write(FCoords, SizeOf(FCoords));
- end;
- procedure TgxCustomCoordinates.NotifyChange(Sender: TObject);
- var
- Int: IgxCoordinatesUpdateAble;
- begin
- if Supports(Owner, IgxCoordinatesUpdateAble, Int) then
- Int.CoordinateChanged(TgxCoordinates(Self));
- inherited NotifyChange(Sender);
- end;
- procedure TgxCustomCoordinates.Translate(const TranslationVector: TGLVector);
- begin
- FCoords.X := FCoords.X + TranslationVector.X;
- FCoords.Y := FCoords.Y + TranslationVector.Y;
- FCoords.Z := FCoords.Z + TranslationVector.Z;
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Translate(const TranslationVector
- : TAffineVector);
- begin
- FCoords.X := FCoords.X + TranslationVector.X;
- FCoords.Y := FCoords.Y + TranslationVector.Y;
- FCoords.Z := FCoords.Z + TranslationVector.Z;
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.AddScaledVector(const Factor: Single;
- const TranslationVector: TGLVector);
- var
- F: Single;
- begin
- F := Factor;
- CombineVector(FCoords, TranslationVector, F);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.AddScaledVector(const Factor: Single;
- const TranslationVector: TAffineVector);
- var
- F: Single;
- begin
- F := Factor;
- CombineVector(FCoords, TranslationVector, F);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Rotate(const AnAxis: TAffineVector;
- AnAngle: Single);
- begin
- RotateVector(FCoords, AnAxis, AnAngle);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Rotate(const AnAxis: TGLVector; AnAngle: Single);
- begin
- RotateVector(FCoords, AnAxis, AnAngle);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Normalize;
- begin
- NormalizeVector(FCoords);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Invert;
- begin
- NegateVector(FCoords);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.Scale(Factor: Single);
- begin
- ScaleVector(PAffineVector(@FCoords)^, Factor);
- NotifyChange(Self);
- end;
- function TgxCustomCoordinates.VectorLength: Single;
- begin
- Result := Stage.VectorGeometry.VectorLength(FCoords);
- end;
- function TgxCustomCoordinates.VectorNorm: Single;
- begin
- Result := Stage.VectorGeometry.VectorNorm(FCoords);
- end;
- function TgxCustomCoordinates.MaxXYZ: Single;
- begin
- Result := MaxXYZComponent(FCoords);
- end;
- function TgxCustomCoordinates.Equals(const AVector: TGLVector): Boolean;
- begin
- Result := VectorEquals(FCoords, AVector);
- end;
- procedure TgxCustomCoordinates.SetVector(const X, Y: Single; Z: Single = 0);
- begin
- Assert(FStyle = csVector, csVectorHelp);
- Stage.VectorGeometry.SetVector(FCoords, X, Y, Z);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetVector(const V: TAffineVector);
- begin
- Assert(FStyle = csVector, csVectorHelp);
- Stage.VectorGeometry.SetVector(FCoords, V);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetVector(const V: TGLVector);
- begin
- Assert(FStyle = csVector, csVectorHelp);
- Stage.VectorGeometry.SetVector(FCoords, V);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetVector(const X, Y, Z, W: Single);
- begin
- Assert(FStyle = csVector, csVectorHelp);
- Stage.VectorGeometry.SetVector(FCoords, X, Y, Z, W);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetDirectCoordinate(const Index: Integer;
- const AValue: Single);
- begin
- FCoords.V[index] := AValue;
- end;
- procedure TgxCustomCoordinates.SetDirectVector(const V: TGLVector);
- begin
- FCoords.X := V.X;
- FCoords.Y := V.Y;
- FCoords.Z := V.Z;
- FCoords.W := V.W;
- end;
- procedure TgxCustomCoordinates.SetToZero;
- begin
- FCoords.X := 0;
- FCoords.Y := 0;
- FCoords.Z := 0;
- if FStyle = CsPoint then
- FCoords.W := 1
- else
- FCoords.W := 0;
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint(const X, Y, Z: Single);
- begin
- Assert(FStyle = CsPoint, CsPointHelp);
- MakePoint(FCoords, X, Y, Z);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint(const V: TAffineVector);
- begin
- Assert(FStyle = CsPoint, CsPointHelp);
- MakePoint(FCoords, V);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint(const V: TGLVector);
- begin
- Assert(FStyle = CsPoint, CsPointHelp);
- MakePoint(FCoords, V);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint2D(const X, Y: Single);
- begin
- Assert(FStyle = CsPoint2D, CsPoint2DHelp);
- Stage.VectorGeometry.MakeVector(FCoords, X, Y, 0);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint2D(const Vector: TAffineVector);
- begin
- Assert(FStyle = CsPoint2D, CsPoint2DHelp);
- MakeVector(FCoords, Vector);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint2D(const Vector: TGLVector);
- begin
- Assert(FStyle = CsPoint2D, CsPoint2DHelp);
- MakeVector(FCoords, Vector);
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetPoint2D(const Vector: TVector2f);
- begin
- Assert(FStyle = CsPoint2D, CsPoint2DHelp);
- MakeVector(FCoords, Vector.X, Vector.Y, 0);
- NotifyChange(Self);
- end;
- function TgxCustomCoordinates.AsAddress: PSingle;
- begin
- Result := @FCoords;
- end;
- procedure TgxCustomCoordinates.SetAsVector(const Value: TGLVector);
- begin
- FCoords := Value;
- case FStyle of
- CsPoint2D:
- begin
- FCoords.Z := 0;
- FCoords.W := 0;
- end;
- CsPoint:
- FCoords.W := 1;
- CsVector:
- FCoords.W := 0;
- else
- Assert(False);
- end;
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetAsAffineVector(const Value: TAffineVector);
- begin
- case FStyle of
- CsPoint2D:
- MakeVector(FCoords, Value);
- CsPoint:
- MakePoint(FCoords, Value);
- CsVector:
- MakeVector(FCoords, Value);
- else
- Assert(False);
- end;
- NotifyChange(Self);
- end;
- procedure TgxCustomCoordinates.SetAsPoint2D(const Value: TVector2f);
- begin
- case FStyle of
- CsPoint2D, CsPoint, CsVector:
- begin
- FCoords.X := Value.X;
- FCoords.Y := Value.Y;
- FCoords.Z := 0;
- FCoords.W := 0;
- end;
- else
- Assert(False);
- end;
- NotifyChange(Self);
- end;
- function TgxCustomCoordinates.GetAsAffineVector: TAffineVector;
- begin
- Stage.VectorGeometry.SetVector(Result, FCoords);
- end;
- function TgxCustomCoordinates.GetAsPoint2D: TVector2f;
- begin
- Result.X := FCoords.X;
- Result.Y := FCoords.Y;
- end;
- procedure TgxCustomCoordinates.SetCoordinate(const AIndex: Integer;
- const AValue: Single);
- begin
- FCoords.V[AIndex] := AValue;
- NotifyChange(Self);
- end;
- function TgxCustomCoordinates.GetCoordinate(const AIndex: Integer): Single;
- begin
- Result := FCoords.V[AIndex];
- end;
- function TgxCustomCoordinates.GetDirectCoordinate(
- const Index: Integer): Single;
- begin
- Result := FCoords.V[index]
- end;
- function TgxCustomCoordinates.GetAsString: String;
- begin
- case Style of
- CsPoint2D:
- Result := Format('(%g; %g)', [FCoords.X, FCoords.Y]);
- CsPoint:
- Result := Format('(%g; %g; %g)', [FCoords.X, FCoords.Y, FCoords.Z]);
- CsVector:
- Result := Format('(%g; %g; %g; %g)', [FCoords.X, FCoords.Y, FCoords.Z,
- FCoords.W]);
- else
- Assert(False);
- end;
- end;
- // ----------------- Conversions of coordinates --------------------
- // ----------------- Cylindrical_Cartesian ----------------------
- procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single);
- begin
- SinCosine(theta, r, y, x);
- z := z1;
- end;
- // ----- Cylindrical_Cartesian -------------------------------------
- procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double);
- begin
- SinCosine(theta, r, y, x);
- z := z1;
- end;
- // ------------------ Cylindrical_Cartesian -----------------------
- procedure Cylindrical_Cartesian(const r, theta, z1: single; var x, y, z: single;
- var ierr: integer);
- begin
- // check input parameters
- if (r < 0.0) then
- ierr := 1
- else if ((theta < 0.0) or (theta >= 2 * pi)) then
- ierr := 2
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(theta, r, y, x);
- z := z1;
- end;
- end;
- // ----- Cylindrical_Cartesian -------------------------------------------------
- procedure Cylindrical_Cartesian(const r, theta, z1: double; var x, y, z: double;
- var ierr: integer);
- begin
- // check input parameters
- if (r < 0.0) then
- ierr := 1
- else if ((theta < 0.0) or (theta >= 2 * pi)) then
- ierr := 2
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(theta, r, y, x);
- z := z1;
- end;
- end;
- // ----- Cartesian_Cylindrical -------------------------------------------------
- procedure Cartesian_Cylindrical(const x, y, z1: single; var r, theta, z: single);
- begin
- r := sqrt(x * x + y * y);
- theta := ArcTan2(y, x);
- z := z1;
- end;
- // ----- Cartesian_Cylindrical -------------------------------------------------
- procedure Cartesian_Cylindrical(const x, y, z1: double; var r, theta, z: double);
- begin
- r := sqrt(x * x + y * y);
- theta := ArcTan2(y, x);
- z := z1;
- end;
- // ----- Spherical_Cartesian ---------------------------------------------------
- procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single);
- var
- a: single;
- begin
- SinCosine(phi, r, a, z); // z = r*cos(phi), a = r*sin(phi)
- SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
- end;
- // ----- Spherical_Cartesian ---------------------------------------------------
- procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double);
- var
- a: double;
- begin
- SinCosine(phi, r, a, z); // z = r*cos(phi), a = r*sin(phi)
- SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
- end;
- // ----- Spherical_Cartesian ---------------------------------------------------
- procedure Spherical_Cartesian(const r, theta, phi: single; var x, y, z: single;
- var ierr: integer);
- var
- a: single;
- begin
- if (r < 0.0) then
- ierr := 1
- else if ((theta < 0.0) or (theta >= 2 * pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(phi, r, a, z); // z = r*cos(phi), a = r*sin(phi)
- SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
- end;
- end;
- // ----- Spherical_Cartesian ---------------------------------------------------
- (* Convert Spherical to Cartesian with checks.
- ierr: [0] = ok,
- [1] = r out of bounds
- [2] = theta out of bounds
- [3] = phi out of bounds
- Ref: http://mathworld.wolfram.com/SphericalCoordinates.html *)
- procedure Spherical_Cartesian(const r, theta, phi: double; var x, y, z: double;
- var ierr: integer);
- var
- a: double;
- begin
- if (r < 0.0) then
- ierr := 1
- else if ((theta < 0.0) or (theta >= 2 * pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(phi, r, a, z); // z = r*cos(phi), a=r*sin(phi)
- SinCosine(theta, a, y, x); // x = a*cos(theta), y = a*sin(theta)}
- end;
- end;
- // ----- Cartesian_Spherical ---------------------------------------------------
- procedure Cartesian_Spherical(const x, y, z: single; var r, theta, phi: single);
- begin
- r := sqrt((x * x) + (y * y) + (z * z));
- theta := ArcTan2(y, x);
- phi := ArcCosine(z / r);
- end;
- procedure Cartesian_Spherical(const v: TAffineVector; var r, theta, phi: single);
- begin
- r := VectorLength(v);
- theta := ArcTan2(v.y, v.x);
- phi := ArcCosine(v.z / r);
- end;
- // ----- Cartesian_Spherical ---------------------------------------------------
- procedure Cartesian_Spherical(const x, y, z: double; var r, theta, phi: double);
- begin
- r := sqrt((x * x) + (y * y) + (z * z));
- theta := ArcTan2(y, x);
- phi := ArcCosine(z / r);
- end;
- // ----- ProlateSpheroidal_Cartesian -------------------------------------------
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single; var x, y, z: single);
- var
- sn, cs, snphi, csphi, shx, chx: single;
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
- y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
- z := cs * chx; // z = a*cos(eta)*cosh(xi)
- end;
- // ----- ProlateSpheroidal_Cartesian -------------------------------------------
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double; var x, y, z: double);
- var
- sn, cs, snphi, csphi, shx, chx: double;
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
- y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
- z := cs * chx; // z = a*cos(eta)*cosh(xi)
- end;
- // ----- ProlateSpheroidal_Cartesian -------------------------------------------
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single; var ierr: integer); overload;
- var
- sn, cs, snphi, csphi, shx, chx: single;
- begin
- if (xi < 0.0) then
- ierr := 1
- else if ((eta < 0.0) or (eta > pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
- y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
- z := cs * chx; // z = a*cos(eta)*cosh(xi)
- end;
- end;
- // ----- ProlateSpheroidal_Cartesian -------------------------------------------
- procedure ProlateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double; var ierr: integer); overload;
- var
- sn, cs, snphi, csphi, shx, chx: double;
- begin
- if (xi < 0.0) then
- ierr := 1
- else if ((eta < 0.0) or (eta > pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := sn * shx * csphi; // x = a*sin(eta)*sinh(xi)*cos(phi)
- y := sn * shx * snphi; // y = a*sin(eta)*sinh(xi)*sin(phi)
- z := cs * chx; // z = a*cos(eta)*cosh(xi)
- end;
- end;
- // ----- OblateSpheroidal_Cartesian -------------------------------------------
- (* Convert Oblate-Spheroidal to Cartesian with no checks.
- A system of curvilinear coordinates in which two sets of coordinate surfaces are
- obtained by revolving the curves of the elliptic cylindrical coordinates about
- the y-axis which is relabeled the z-axis. The third set of coordinates consists
- of planes passing through this axis.
- The coordinate system is parameterised by parameter a. A default value of a=1 is
- suggesed:
- http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
- Ref: http://mathworld.wolfram.com/OblateSpheroidalCoordinates.html *)
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single; var x, y, z: single);
- var
- sn, cs, snphi, csphi, shx, chx: single;
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
- y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
- z := sn * shx; // z = a*sin(eta)*sinh(xi)
- end;
- // ----- OblateSpheroidal_Cartesian -------------------------------------------
- (* Convert Oblate-Spheroidal to Cartesian with no checks. Double Version.
- A system of curvilinear coordinates in which two sets of coordinate surfaces are
- obtained by revolving the curves of the elliptic cylindrical coordinates about
- the y-axis which is relabeled the z-axis. The third set of coordinates consists
- of planes passing through this axis.
- The coordinate system is parameterised by parameter a. A default value of a=1 is
- suggesed:
- http://documents.wolfram.com/v4/AddOns/StandardPackages/Calculus/VectorAnalysis.html
- Ref: http://mathworld.wolfram.com/OblateSpheroidalCoordinates.html *)
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double; var x, y, z: double);
- var
- sn, cs, snphi, csphi, shx, chx: double;
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
- y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
- z := sn * shx; // z = a*sin(eta)*sinh(xi)
- end;
- // ----- OblateSpheroidal_Cartesian -------------------------------------------
- (* Convert Oblate-Spheroidal to Cartesian with checks.
- ierr: [0] = ok,
- [1] = xi out of bounds. Acceptable xi: [0,inf)
- [2] = eta out of bounds. Acceptable eta: [-0.5*pi,0.5*pi]
- [3] = phi out of bounds. Acceptable phi: [0,2*pi)
- Ref: http://mathworld.wolfram.com/ProlateSpheroidalCoordinates.html *)
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: single;
- var x, y, z: single; var ierr: integer); overload;
- var
- sn, cs, snphi, csphi, shx, chx: single;
- begin
- if (xi < 0.0) then
- ierr := 1
- else if ((eta < -0.5 * pi) or (eta > 0.5 * pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
- y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
- z := sn * shx; // z = a*sin(eta)*sinh(xi)
- end;
- end;
- // ----- OblateSpheroidal_Cartesian -------------------------------------------
- procedure OblateSpheroidal_Cartesian(const xi, eta, phi, a: double;
- var x, y, z: double; var ierr: integer); overload;
- var
- sn, cs, snphi, csphi, shx, chx: double;
- begin
- if (xi < 0.0) then
- ierr := 1
- else if ((eta < -0.5 * pi) or (eta > 0.5 * pi)) then
- ierr := 2
- else if ((phi < 0.0) or (phi >= 2 * pi)) then
- ierr := 3
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(eta, a, sn, cs);
- SinCosine(phi, snphi, csphi);
- shx := sinh(xi);
- chx := cosh(xi);
- x := cs * chx * csphi; // x = a*cos(eta)*cosh(xi)*cos(phi)
- y := cs * chx * snphi; // y = a*cos(eta)*cosh(xi)*sin(phi)
- z := sn * shx; // z = a*sin(eta)*sinh(xi)
- end;
- end;
- // ----- BipolarCylindrical_Cartesian ------------------------------------------
- (* Convert BiPolarCylindrical to Cartesian with no checks.
- http://mathworld.wolfram.com/BipolarCylindricalCoordinates.html *)
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single; var x, y, z: single);
- var
- cs, sn, shx, chx: single;
- begin
- SinCosine(u, sn, cs);
- shx := sinh(v);
- chx := cosh(v);
- x := a * shx / (chx - cs);
- y := a * sn / (chx - cs);
- z := z1;
- end;
- // ----- BipolarCylindrical_Cartesian ------------------------------------------
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double; var x, y, z: double);
- var
- cs, sn, shx, chx: double;
- begin
- SinCosine(u, sn, cs);
- shx := sinh(v);
- chx := cosh(v);
- x := a * shx / (chx - cs);
- y := a * sn / (chx - cs);
- z := z1;
- end;
- // ----- BipolarCylindrical_Cartesian ------------------------------------------
- (* Convert Oblate-Spheroidal to Cartesian with checks.
- ierr: [0] = ok,
- [1] = u out of bounds. Acceptable u: [0,2*pi)
- [2] = v out of bounds. Acceptable v: (-inf,inf)
- [3] = z1 out of bounds. Acceptable z1: (-inf,inf)
- Ref: http://mathworld.wolfram.com/BiPolarCylindricalCoordinates.html *)
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: single;
- var x, y, z: single; var ierr: integer); overload;
- var
- cs, sn, shx, chx: single;
- begin
- if ((u < 0.0) or (u >= 2 * pi)) then
- ierr := 1
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(u, sn, cs);
- shx := sinh(v);
- chx := cosh(v);
- x := a * shx / (chx - cs);
- y := a * sn / (chx - cs);
- z := z1;
- end;
- end;
- // ----- BipolarCylindrical_Cartesian ------------------------------------------
- procedure BipolarCylindrical_Cartesian(const u, v, z1, a: double;
- var x, y, z: double; var ierr: integer); overload;
- var
- cs, sn, shx, chx: double;
- begin
- if ((u < 0.0) or (u >= 2 * pi)) then
- ierr := 1
- else
- ierr := 0;
- if (ierr = 0) then
- begin
- SinCosine(u, sn, cs);
- shx := sinh(v);
- chx := cosh(v);
- x := a * shx / (chx - cs);
- y := a * sn / (chx - cs);
- z := z1;
- end;
- end;
- function BarycentricCoordinates(const V1, V2, V3, p: TAffineVector;
- var u, V: Single): Boolean;
- var
- a1, a2: Integer;
- n, e1, e2, pt: TAffineVector;
- begin
- // calculate edges
- VectorSubtract(V1, V3, e1);
- VectorSubtract(V2, V3, e2);
- // calculate p relative to v3
- VectorSubtract(p, V3, pt);
- // find the dominant axis
- n := VectorCrossProduct(e1, e2);
- AbsVector(n);
- a1 := 0;
- if n.Y > n.V[a1] then
- a1 := 1;
- if n.Z > n.V[a1] then
- a1 := 2;
- // use dominant axis for projection
- case a1 of
- 0:
- begin
- a1 := 1;
- a2 := 2;
- end;
- 1:
- begin
- a1 := 0;
- a2 := 2;
- end;
- else // 2:
- a1 := 0;
- a2 := 1;
- end;
- // solve for u and v
- u := (pt.V[a2] * e2.V[a1] - pt.V[a1] * e2.V[a2]) /
- (e1.V[a2] * e2.V[a1] - e1.V[a1] * e2.V[a2]);
- V := (pt.V[a2] * e1.V[a1] - pt.V[a1] * e1.V[a2]) /
- (e2.V[a2] * e1.V[a1] - e2.V[a1] * e1.V[a2]);
- result := (u >= 0) and (V >= 0) and (u + V <= 1);
- end;
- initialization //------------------------------------------------------------
- RegisterClasses([TgxCoordinates2, TgxCoordinates3, TgxCoordinates4]);
- finalization //--------------------------------------------------------------
- // UnRegisterClasses([TgxCoordinates2, TgxCoordinates3, TgxCoordinates4]);
- end.
|