⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dxlines.pas

📁 业生产并行开发过程 工作流流程编辑器参考源码 采用dxflowchart编写
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{*******************************************************************}
{                                                                   }
{       Developer Express Visual Component Library                  }
{       ExpressFlowChart                                            }
{                                                                   }
{       Copyright (c) 1998-2004 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE    }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE EXPRESSFLOWCHART AND ALL ACCOMPANYING}
{   VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.             }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE end USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}

unit dxLines;

interface

uses Windows,Classes;

type TLineType = (liStraight, liQSpline, liRectH, liRectV);

procedure QSpline(DC: HDC; var Points; Count: Integer);
procedure RectHLine(DC: HDC; var Points; Count: Integer);
procedure RectVLine(DC: HDC; var Points; Count: Integer);
procedure ExtendRect(var R: TRect; const P: TPoint);
function Distance(const A,B: TPoint): Integer;
function LineLength(LType: TLineType; var Points; Count: Integer): Integer;
function LineCenter(LType: TLineType; var Points; Count: Integer): TPoint;
function MassCenter(LType: TLineType; var Points; Count: Integer): TPoint;
function PtOnLine(LType: TLineType; var Points; Count,Delta,X,Y: Integer): Boolean;
function RectOnLine(LType: TLineType; var Points; Count: Integer; const R: TRect): Boolean;
function PointIndex: Integer;

implementation

type

  TQSData = packed record
    P0,P1,P2: TPoint;
    Px2,DPx2,Qx: TPoint;
    Result: Integer;
    Step,Limit: Word;
    Mode,Last: Byte;
    case Integer of
    0: (Source,Prev: TPoint);
    1: (Rect: TRect);
  end;

  TPointArray = array[0..$FFFFFF] of TPoint;
  PPointArray = ^TPointArray;
  PPoint = ^TPoint;
  TPointFunc = function(LType:TLineType;P:PPointArray;I,Count:Integer;var Data: TQSData): Boolean;

var LastIndex: Integer;

{ Service public routines }

procedure ExtendRect(var R: TRect; const P: TPoint);
begin
  if P.X < R.Left then R.Left := P.X;
  if P.X > R.Right then R.Right := P.X;
  if P.Y < R.Top then R.Top := P.Y;
  if P.Y > R.Bottom then R.Bottom := P.Y;
end;

function Distance(const A,B: TPoint): Integer;
var
  DX, DY: Extended;
begin
  try
    DX := A.X - B.X;
    DY := A.Y - B.Y;
    if (DX=0) or (DY=0) then
      Result := Round(Abs(DX+DY))
    else
      Result := Round(Sqrt(DX * DX + DY * DY));
  except
    Result := 0;
  end;
end;

{ Internal routines }

procedure QSPoints(var Data: TQSData); register;
asm
    JMP	@MAIN

@ABSMAX:	MOV	EAX,[EBX]
    SUB	EAX,[ECX]
    JNS	@@A1
    NEG	EAX
@@A1:		MOV	EDX,[EBX].4
    SUB	EDX,[ECX].4
    JNS	@@A2
    NEG	EDX
@@A2:		CMP	EAX,EDX
    JAE	@@A3
    XCHG	EAX,EDX
@@A3:		RET

@INIT:		XOR	EBX,EBX
    MOV	EBP,EBX
    MOV	BP,AX
    CALL	@@I1
    INC	EBX
@@I1:		MOV	EAX,[ESI+EBX*4].TQSData.P0.X
    ADD	EAX,[ESI+EBX*4].TQSData.P2.X
    SUB	EAX,[ESI+EBX*4].TQSData.P1.X
    SUB	EAX,[ESI+EBX*4].TQSData.P1.X
    IMUL	EBP
    IMUL	EBP
    SHRD	EAX,EDX,15
    ADC	EAX,0
    MOV	[ESI+EBX*4].TQSData.DPx2.X,EAX
    SAR	EAX,1
    ADC	EAX,0
    MOV	[ESI+EBX*4].TQSData.Px2.X,EAX
    MOV	EAX,[ESI+EBX*4].TQSData.P1.X
    SUB	EAX,[ESI+EBX*4].TQSData.P0.X
    SAL	EAX,1
    IMUL	EBP
    ADD	[ESI+EBX*4].TQSData.Px2.X,EAX
    MOV	[ESI+EBX*4].TQSData.Qx.X,0
    MOV	EAX,[ESI+EBX*4].TQSData.P0.X
    MOV	[ESI+EBX*4].TQSData.P1.X,EAX
    RET

@NEXT:		XOR	EBX,EBX
    CALL	@@N1
    INC	EBX
@@N1:		MOV	EAX,[ESI+EBX*4].TQSData.Px2.X
    ADD	EAX,[ESI+EBX*4].TQSData.Qx.X
    MOV	[ESI+EBX*4].TQSData.Qx.X,EAX
    SAR	EAX,16
    ADC	EAX,[ESI+EBX*4].TQSData.P1.X
    MOV	[ESI+EBX*4].TQSData.P0.X,EAX
    MOV	EAX,[ESI+EBX*4].TQSData.DPx2.X
    ADD	[ESI+EBX*4].TQSData.Px2.X,EAX
    RET

@DO_PTS:	MOV	EAX,[ESI].TQSData.P0.X
    STOSD
    MOV	EAX,[ESI].TQSData.P0.Y
    STOSD
    RET

@MAIN:		PUSH	EBX
    PUSH	EBP
    PUSH	ESI
    PUSH	EDI
    MOV	ESI,EAX
    LEA	EBX,[ESI].TQSData.P0
    LEA	ECX,[ESI].TQSData.P1
    CALL	@ABSMAX
    MOV	EBP,EAX
    LEA	EBX,[ESI].TQSData.P2
    CALL	@ABSMAX
    ADD	EBP,EAX
    JZ	@@END
    XOR	EAX,EAX
    CDQ
    MOV	DL,8
@@1:		CMP	DX,BP
    JB	@@2
    SAL	EBP,1
    JMP	@@1
@@2:		DIV	BP
    MOV	[ESI].TQSData.Step,AX
    MOV	[ESI].TQSData.Limit,0
    CALL	@INIT
    MOV	EDI,[ESI].TQSData.Result
@@3:		CALL	@DO_PTS
    CALL	@NEXT
    MOV	AX,[ESI].TQSData.Step
    ADD	[ESI].TQSData.Limit,AX
    JNC	@@3
    MOV	EAX,[ESI].TQSData.P2.X
    MOV	[ESI].TQSData.P0.X,EAX
    MOV	EAX,[ESI].TQSData.P2.Y
    MOV	[ESI].TQSData.P0.Y,EAX
    CMP	[ESI].TQSData.Last,0
    JZ	@@4
    CALL	@DO_PTS
@@4:		MOV	[ESI].TQSData.Result,EDI
@@END:		POP	EDI
    POP	ESI
    POP	EBP
    POP	EBX
end;

function StackAlloc(Size: Integer): Pointer; register;
asm
    POP	ECX
    MOV	EDX,ESP
    ADD	EAX,3
    AND	AL,NOT 3
@@1:		CMP	EAX,4092
    JBE	@@2
    SUB	ESP,4092
    PUSH	EAX
    SUB	EAX,4096
    JMP	@@1
@@2:		SUB	ESP,EAX
    MOV	EAX,ESP
    PUSH	EDX
    PUSH	ECX
end;

procedure StackFree(P: Pointer); register;
asm
    POP	ECX
    MOV	ESP,[EAX].-4
    PUSH	ECX
end;

procedure MiddlePoint(var Dst: TPoint; const Src: TPoint);
begin
  Dst.X := Src.X + (Dst.X - Src.X) div 2;
  Dst.Y := Src.Y + (Dst.Y - Src.Y) div 2;
end;

procedure DoQSPoints(const Points: array of TPoint; Count: Integer; var Data: TQSData);
var I: Integer;
begin
  with Data do begin
    P0 := Points[0];
    Last := 0;
    for I:=1 to Count-2 do begin
      P1 := Points[I];
      P2 := Points[I+1];
      if I = Count-2 then Last := 1
      else MiddlePoint(P2,P1);
      QSPoints(Data);
    end;
  end;
end;

{$O-}
procedure RectLine(DC: HDC; var Points; Count: Integer; Vertical: Boolean);
var
  I,J: Integer;
  P1,P2: ^TPointArray;
begin
  if Count < 2 then Exit;
  P1 := @Points; P2 := StackAlloc(Count shl 4);
  J := 0; P2^[0] := P1^[0];
  for I:=1 to Count-1 do begin
    Inc(J); P2^[J] := P2^[J-1];
    if Vertical then P2^[J].Y := P1^[I].Y
    else P2^[J].X := P1^[I].X;
    Inc(J); P2^[J] := P1^[I];
  end;
  Polyline(DC,P2^,Count shl 1 - 1);
  StackFree(P2);
end;
{$O+}

function PartLen(LType: TLineType; P: PPointArray; I,Count: Integer; LC,MC: PPoint): Integer;
var
  Ax,Bx,Ay,By,A,C: Integer;
  W,B2A,SqA,L0,T,DT: Extended;
  P0,P1,P2: TPoint;

  procedure RectPoints;
  begin
    P0 := Point(P^[I+1].X,P^[I].Y);
    P1 := Point(P^[I].X,P^[I+1].Y);
    if P0.X < P1.X then Ax := -Ax;
    if P1.Y < P0.Y then Ay := -Ay;
    Dec(P0.X,Ax); Inc(P0.Y,Ay);
    Inc(P1.X,Ax); Dec(P1.Y,Ay);
  end;

  function Limits(X: Extended): Extended;
  var S: Extended;
  begin
    if W=0 then Result := X * Abs(X)
    else begin
      S := Sqrt(X*X + W);
      Result := X*S + W*Ln(X+S);
    end;
  end;

begin
  Bx := 0;
  By := 0;
  B2A := 0;
  Result := 0;
  SqA := 0;
  L0 := 0;
  case LType of
    liStraight: Result := Distance(P^[I],P^[I+1]);
    liRectH,liRectV: Result := Abs(P^[I].X - P^[I+1].X) + Abs(P^[I].Y - P^[I+1].Y);
    liQSpline: begin
      P0 := P^[I]; P1 := P^[I+1]; P2 := P^[I+2];
      if I > 0 then MiddlePoint(P0,P1);
      if I < Count-2 then MiddlePoint(P2,P1);
      Ax := P0.X + P2.X - P1.X shl 1; Bx := P1.X - P0.X;
      Ay := P0.Y + P2.Y - P1.Y shl 1; By := P1.Y - P0.Y;
      A := Ax*Ax + Ay*Ay; C := Bx*Bx + By*By; W := 0;
      if A=0 then Result := Round(Sqrt(C shl 2))
      else begin
  B2A := (Ax*Bx + Ay*By) / A; W := C/A - B2A*B2A;
  SqA := Sqrt(A); L0 := Limits(B2A);
  Result := Round(SqA*(Limits(B2A+1)-L0));
      end;
    end;
  end;
  if LC <> nil then case LType of
    liStraight: begin
      A := LC^.X; C := LC^.Y;
      LC^.X := P^[I].X + MulDiv(P^[I+1].X-P^[I].X,A,C);
      LC^.Y := P^[I].Y + MulDiv(P^[I+1].Y-P^[I].Y,A,C);
    end;
    liRectH,liRectV: begin
      Ax := Abs(P^[I].X - P^[I+1].X) - LC^.X;
      if Ax >= 0 then Ay := 0
      else begin
  Ay := -Ax;
  Ax := 0;
      end;
      RectPoints;
      if LType=liRectH then LC^ := P0 else LC^ := P1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -