📄 ezdxfutil.pas
字号:
Unit EzDxfUtil;
{***********************************************************}
{ EzGIS/CAD Components }
{ (c) 2003 EzSoft Engineering }
{ All Rights Reserved }
{***********************************************************}
{$I EZ_FLAG.PAS}
Interface
Uses
SysUtils, windows, Graphics, Math;
Type
Point3D = Record
x, y, z: Double;
End;
Point2D = Record
x, y: Double;
End;
PPoint3D = ^Point3D;
ppointlist = ^pointlist;
pointlist = Array[0..1000000] Of Point3D;
Const
origin3D: Point3D = ( x: 0; y: 0; z: 0 );
WCS_X: Point3D = ( x: 1; y: 0; z: 0 );
WCS_Y: Point3D = ( x: 0; y: 1; z: 0 );
WCS_Z: Point3D = ( x: 0; y: 0; z: 1 );
Type
pMatrix = ^Matrix;
pM = pMatrix;
Matrix = Record
val: Array[0..3, 0..3] Of Double;
End;
Const
identity: Matrix = ( val: ( ( 1, 0, 0, 0 ), ( 0, 1, 0, 0 ), ( 0, 0, 1, 0 ), ( 0, 0, 0, 1 ) ) );
Var
Handle: longint;
///////////////////////////////////////////////////////////////////////////////
// General point 3D stuff
///////////////////////////////////////////////////////////////////////////////
Function aPoint3D( a, b, c: Double ): Point3D;
Function p1_eq_p2_3D( p1, p2: Point3D ): boolean;
Function p1_eq_p2_2D( p1, p2: Point3D ): boolean;
Function p1_minus_p2( p1, p2: Point3D ): Point3D;
Function p1_plus_p2( p1, p2: Point3D ): Point3D;
Function normalize( p1: Point3D ): Point3D;
//Function mag( p1: Point3D ): Double;
Function dist3D( p1, p2: Point3D ): Double;
Function dist2D( p1, p2: Point3D ): Double;
Function sq_dist3D( p1, p2: Point3D ): Double;
Function sq_dist2D( p1, p2: Point3D ): Double;
Function sq_mag3D( p1: Point3D ): Double;
Function p1_x_n( p1: Point3D; n: Double ): Point3D;
Function set_accuracy( factor: Double; p: Point3D ): Point3D;
///////////////////////////////////////////////////////////////////////////////
// Vector 3D stuff
///////////////////////////////////////////////////////////////////////////////
//Function dot( p1, p2: Point3D ): Double;
Function cross( p1, p2: Point3D ): Point3D;
Function angle( p1, p2, p3: Point3D; do_3D: boolean ): Double;
///////////////////////////////////////////////////////////////////////////////
// Rotations for Insert/Block drawing
///////////////////////////////////////////////////////////////////////////////
Function XRotateMatrix( cos_a, sin_a: Double ): Matrix;
Function YRotateMatrix( cos_a, sin_a: Double ): Matrix;
Function ZRotateMatrix( cos_a, sin_a: Double ): Matrix;
Function ScaleMatrix( p: Point3D ): Matrix;
Function TranslateMatrix( p: Point3D ): Matrix;
Function MatrixMultiply( const matrix1, matrix2: Matrix ): Matrix;
Function CreateTransformation( const Ax, Ay, Az: Point3D ): Matrix;
Function TransformPoint( TM: Matrix; p: Point3D ): Point3D;
Function update_transformations( OCS_WCS, OCS: pMatrix ): pMatrix;
Function RotationAxis( const A: Point3D; angle: Double ): Matrix;
///////////////////////////////////////////////////////////////////////////////
// Bounds
///////////////////////////////////////////////////////////////////////////////
Procedure max_bound( Var bounds: Point3D; point: Point3D );
Procedure min_bound( Var bounds: Point3D; point: Point3D );
///////////////////////////////////////////////////////////////////////////////
// Memory
///////////////////////////////////////////////////////////////////////////////
Function allocate_points( n: integer ): ppointlist;
Procedure deallocate_points( Var pts: ppointlist; n: integer );
Function allocate_matrix: pMatrix;
Procedure deallocate_matrix( Var m: pMatrix );
///////////////////////////////////////////////////////////////////////////////
// String
///////////////////////////////////////////////////////////////////////////////
Function float_out( f: Double ): String;
Function BoolToStr( b: boolean ): String;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//Function NPoint2D( X, Y: Double ): Point2D;
//Function NPoint3D( X, Y, Z: Double ): Point3D;
//Function NDist2D( P: Point2D ): Double;
//Function NDist3D( P: Point3D ): Double;
Function RoundPoint( P: Point2D ): TPoint;
Function FloatPoint( P: TPoint ): Point2D;
//Function Angle2D( P: Point2D ): Double;
Function RelAngle2D( PA, PB: Point2D ): Double;
Function RelDist2D( PA, PB: Point2D ): Double;
Function RelDist3D( PA, PB: Point3D ): Double;
Procedure Rotate2D( Var P: Point2D; Angle2D: Double );
Procedure RelRotate2D( Var P: Point2D; PCentr: Point2D; Angle2D: Double );
Procedure Move2D( Var P: Point2D; Angle2D, Distance: Double );
Function Between( PA, PB: Point2D; Preference: Double ): Point2D;
//Function DistLine( A, B, C: Double; P: Point2D ): Double;
//Function Dist2P( P, P1, P2: Point2D ): Double;
//Function DistD1P( DX, DY: Double; P1, P: Point2D ): Double;
Function NearLine2P( P, P1, P2: Point2D; D: Double ): Boolean;
//Function AddPoints( P1, P2: Point2D ): Point2D;
//Function SubPoints( P1, P2: Point2D ): Point2D;
Function Invert( Col: TColor ): TColor;
Function Dark( Col: TColor; Percentage: Byte ): TColor;
Function Light( Col: TColor; Percentage: Byte ): TColor;
Function Mix( Col1, Col2: TColor; Percentage: Byte ): TColor;
Function MMix( Cols: Array Of TColor ): TColor;
Function Log( Base, Value: Double ): Double;
Function Modulator( Val, Max: Double ): Double;
Function M( I, J: Integer ): Integer;
Function Tan( Angle2D: Double ): Double;
Procedure Limit( Var Value: Integer; Min, Max: Integer );
Function Exp2( Exponent: Byte ): Word;
Implementation
Function aPoint3D( a, b, c: Double ): Point3D;
Begin
result.x := a;
result.y := b;
result.z := c;
End;
Function p1_eq_p2_3D( p1, p2: Point3D ): boolean;
Begin
result := ( p1.x = p2.x ) And ( p1.y = p2.y ) And ( p1.z = p2.z );
End;
Function p1_eq_p2_2D( p1, p2: Point3D ): boolean;
Begin
result := ( p1.x = p2.x ) And ( p1.y = p2.y );
End;
Function p1_minus_p2( p1, p2: Point3D ): Point3D;
Begin
Try
result.x := p1.x - p2.x;
result.y := p1.y - p2.y;
result.z := p1.z - p2.z;
Except
result := p2;
End;
End;
Function p1_plus_p2( p1, p2: Point3D ): Point3D;
Begin
result.x := p1.x + p2.x;
result.y := p1.y + p2.y;
result.z := p1.z + p2.z;
End;
Function normalize( p1: Point3D ): Point3D;
Var
mag: Double;
Begin
mag := Sqrt( sqr( p1.x ) + sqr( p1.y ) + sqr( p1.z ) );
If mag = 0 Then
mag := 1;
result.x := p1.x / mag;
result.y := p1.y / mag;
result.z := p1.z / mag;
End;
Function mag( p1: Point3D ): Double;
Begin
With p1 Do
result := Sqrt( sqr( x ) + sqr( y ) + sqr( z ) );
End;
Function dist3D( p1, p2: Point3D ): Double;
Begin
With p1_minus_p2( p2, p1 ) Do
result := Sqrt( sqr( x ) + sqr( y ) + sqr( z ) );
End;
Function dist2D( p1, p2: Point3D ): Double;
Begin
With p1_minus_p2( p2, p1 ) Do
result := Sqrt( sqr( x ) + sqr( y ) );
End;
Function sq_dist3D( p1, p2: Point3D ): Double;
Begin
With p1_minus_p2( p2, p1 ) Do
result := sqr( x ) + sqr( y ) + sqr( z );
End;
Function sq_dist2D( p1, p2: Point3D ): Double;
Begin
Try
With p1_minus_p2( p2, p1 ) Do
result := sqr( x ) + sqr( y );
Except
result := 0;
End;
End;
Function sq_mag3D( p1: Point3D ): Double;
Begin
With p1 Do
result := sqr( x ) + sqr( y ) + sqr( z );
End;
Function p1_x_n( p1: Point3D; n: Double ): Point3D;
Begin
result.x := p1.x * n;
result.y := p1.y * n;
result.z := p1.z * n;
End;
Function set_accuracy( factor: Double; p: Point3D ): Point3D;
Begin
result.x := round( p.x * factor ) / factor;
result.y := round( p.y * factor ) / factor;
result.z := round( p.z * factor ) / factor;
End;
///////////////////////////////////////////////////////////////////////////////
// Vector 3D stuff
///////////////////////////////////////////////////////////////////////////////
Function dot( p1, p2: Point3D ): Double;
Begin
result := p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
End;
Function cross( p1, p2: Point3D ): Point3D;
Begin
result.x := p1.y * p2.z - p1.z * p2.y;
result.y := p1.z * p2.x - p1.x * p2.z;
result.z := p1.x * p2.y - p1.y * p2.x;
End;
Function angle( p1, p2, p3: Point3D; do_3D: boolean ): Double;
Var
v1, v2: Point3D;
d1, d2: Double;
Begin
v1 := p1_minus_p2( p2, p1 );
v2 := p1_minus_p2( p3, p2 );
If Not do_3D Then
Begin
v1.z := 0;
v2.z := 0;
End;
d1 := Mag( v1 );
d2 := Mag( v2 );
If ( ( d1 = 0 ) Or ( d2 = 0 ) ) Then
result := 0
Else
Begin
d1 := dot( v1, v2 ) / ( d1 * d2 );
If abs( d1 ) <= 1 Then
result := ArcCos( d1 )
Else
result := 0;
End;
End;
///////////////////////////////////////////////////////////////////////////////
// Rotations for Insert/Block drawing
///////////////////////////////////////////////////////////////////////////////
Function XRotateMatrix( cos_a, sin_a: Double ): Matrix;
Begin
result := identity;
result.val[1, 1] := cos_a;
result.val[1, 2] := -sin_a;
result.val[2, 1] := sin_a;
result.val[2, 2] := cos_a;
End;
Function YRotateMatrix( cos_a, sin_a: Double ): Matrix;
Begin
result := identity;
result.val[0, 0] := cos_a;
result.val[0, 2] := sin_a;
result.val[2, 0] := -sin_a;
result.val[2, 2] := cos_a;
End;
Function ZRotateMatrix( cos_a, sin_a: Double ): Matrix;
Begin
result := identity;
result.val[0, 0] := cos_a;
result.val[0, 1] := -sin_a;
result.val[1, 0] := sin_a;
result.val[1, 1] := cos_a;
End;
Function ScaleMatrix( p: Point3D ): Matrix;
Begin
result := identity;
result.val[0, 0] := p.x;
result.val[1, 1] := p.y;
result.val[2, 2] := p.z;
End;
Function TranslateMatrix( p: Point3D ): Matrix;
Begin
result := identity;
result.val[3, 0] := p.x;
result.val[3, 1] := p.y;
result.val[3, 2] := p.z;
End;
Function MatrixMultiply( const matrix1, matrix2: matrix ): Matrix;
Var
row, column: integer;
Begin
For row := 0 To 3 Do
Begin
For column := 0 To 3 Do
result.val[row, column] :=
matrix1.val[row, 0] * matrix2.val[0, column] + matrix1.val[row, 1] * matrix2.val[1, column] +
matrix1.val[row, 2] * matrix2.val[2, column] + matrix1.val[row, 3] * matrix2.val[3, column];
End;
End;
Var
GlobalTempMatrix: Matrix;
Function update_transformations( OCS_WCS, OCS: pMatrix ): pMatrix;
Begin
If OCS = Nil Then
result := OCS_WCS
Else If OCS_WCS = Nil Then
result := OCS
Else
Begin
GlobalTempMatrix := MatrixMultiply( OCS_WCS^, OCS^ );
result := @GlobalTempMatrix;
End;
End;
{ Matrix order : For reference
start with a point at ( cos(30),sin(30),0 )
rotate by 30 degrees - shifts point to (1,0,0)
then translate by (10,0,0) shifts to (11,0,0)
then rotate by -45 degrees goes to (7.77, 7.77 ,0) 7.77 = Sqrt(11^2 /2 )
NOTE THE ORDER OF MATRIX OPERATIONS !
test := aPoint3D( cos(degtorad(30)) , sin(degtorad(30)) , 0);
mat := ZRotateMatrix( cos(degtorad(30)) , sin(degtorad(30)) );
mat := MatrixMultiply( mat , TranslateMatrix(aPoint3D(10,0,0)) );
mat := MatrixMultiply( mat , ZRotateMatrix( cos(degtorad(-45)) , sin(degtorad(-45)) ) );
test := TransformPoint(mat,test);
}
Function CreateTransformation( const Ax, Ay, Az: Point3D ): Matrix;
Begin
result := Identity;
result.val[0, 0] := Ax.x;
result.val[1, 0] := Ay.x;
result.val[2, 0] := Az.x;
result.val[0, 1] := Ax.y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -