zoukankan      html  css  js  c++  java
  • GIS基本函数类库Delphi代码

    unit utgispub;
    
    interface
    
    uses
        Math;
    
    type
        uPoint = record
            X, Y: Double;
        end;
        uPoints = array of uPoint;
    
    //方位角: 输入线段(X1,Y1)-(X2,Y2); 返回方位角
    function GetLineAngle(X1, Y1, X2, Y2: Double): Double;
    //长度: 输入线段(X1,Y1)-(X2,Y2); 返回长度
    function GetLineLength(X1, Y1, X2, Y2: Double): Double;
    //顺时针角度: 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3); 返回True(顺时针)或False(逆时针)
    function IsClockwise(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    //顺时针: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 返回True(顺时针)或False(逆时针)
    function IsClockwiseEx(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Boolean;
    //点到直线距离: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 返回距离
    function GetVertDist(X1, Y1, X2, Y2, X3, Y3: Double): Double;
    //垂足: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 输出垂足(X,Y)
    procedure GetVertXY(X1, Y1, X2, Y2, X3, Y3: Double; var X, Y: Double);
    //线段端点(X2,Y2)处垂线上指定长度的点
    //输入线段(X1,Y1)-(X2,Y2)、距离d; 输出点(LX,LY)、(RX,RY); 若线段端点重合返回False
    function GetVertDistXY(X1, Y1, X2, Y2, d: Double; var LX, LY, RX, RY: Double): Boolean;
    //线段端点(X2,Y2)方向延长线上指定长度的点
    //输入线段(X1,Y1)-(X2,Y2)、距离d; 输出点(LX,LY)、(RX,RY); 若线段端点重合返回False
    function GetExtendDistXY(X1, Y1, X2, Y2, d: Double; var LX, LY, RX, RY: Double): Boolean;
    //对称点:输入点(X1,Y1)、(X0,Y0); 输出点(X1,Y1)关于(X0,Y0)的对称点
    procedure GetSymmetricXY(X1, Y1, X0, Y0: Double; var X, Y: Double);
    //两直线夹角: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 返回夹角(<180)
    function GetIntersectAngle(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Double;
    //判断两直线有无交点: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 若两线段有交点返回True
    function IsLineIntersect(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Boolean;
    //两直线交点: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 输出交点(X,Y); 若两线段平行返回False
    function GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double; var X, Y: Double): Boolean;
    //过点作线段的平行线: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 输出平行线(LX,LY)-(RX,RY); 若线段端点重合返回False
    function GetParaLineByPoint(X1, Y1, X2, Y2, X3, Y3: Double; var LX, LY, RX, RY: Double): Boolean;
    //作线段某侧一定距离的平行线: 输入线段(X1,Y1)-(X2,Y2)、距离Dist、位置FlagLeft; 输出平行线(LX,LY)-(RX,RY); 若线段端点重合返回False
    function GetParaLineByDist(X1, Y1, X2, Y2, Dist: Double; FlagLeft: Boolean; var LX, LY, RX, RY: Double): Boolean;
    //作连续线某侧一定距离的平行线: 输入连续线InPts、距离Dist、位置FlagLeft; 输出平行连续线OutPts; 若线段端点重合返回False
    function GetParaLineByDistEx(var InPts: uPoints; Dist: Double; FlagLeft: Boolean; var OutPts: uPoints): Boolean;
    //作两线段的中心线: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 输出平行线(LX,LY)-(RX,RY); 若线段端点重合返回False
    function GetCentreline(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double; var LX, LY, RX, RY: Double): Boolean;
    //作线段的参考线: 输入线段(X1,Y1)-(X2,Y2)、角度(-360~360); 输出与已知线段成已知角度的线段的另一端点(X,Y); 若线段端点重合返回False
    function GetAngleLine(X1, Y1, X2, Y2: Double; angle: Double; var X, Y: Double): Boolean;
    //点在直线内侧: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 若点在线段内侧返回True,否则返回False
    function IsPointInsideLine(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    //点在直线上: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 若点在线段上返回True,否则返回False
    function IsPointOnLine(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    //点在相交区域:输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、点(X,Y); 输出点所在相交区域的端点(LX,LY)、(RX,RY)
    //若线段相交返回True,否则返回False
    function GetIntersectRegion(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y: Double; var X0, Y0, LX, LY, RX, RY: Double): Boolean;
    //梯形顶点:输入方向线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、给定面积A;
    //输出梯形顶点(LX1,LY1)、(LX2,LY2)和(RX1,RY1)、(RX2,RY2), 若梯形存在返回True,否则返回False
    function GetTrapezoidNodes(X1, Y1, X2, Y2, X3, Y3, X4, Y4, A: Double;
        var LX1, LY1, RX1, RY1, LX2, LY2, RX2, RY2: Double): Boolean;
    
    //三角形重心(垂直平分线交点): 输入点(X1,Y1)、(X2,Y2)、(X3,Y3), 若不在一直线上输出重心(X,Y),返回True,否则返回False
    function GetWeightCenter(X1, Y1, X2, Y2, X3, Y3: Double; var X, Y: Double): Boolean;
    
    //过三点作弧1(用于MapX): 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3),
    //输出(X1,Y1)-(X3,Y3)之中点到以(X1,Y1)、(X3,Y3)为切点的圆弧切线交点的距离Dist以及夹角常数Angle(90°/270°)
    //若三点共线无法形成圆弧返回False, 否则返回True
    function GetArcBy3PointsMapX(X1, Y1, X2, Y2, X3, Y3: Double; var Angle, Dist: Double): Boolean;
    //过三点作弧1(折线成弧): 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3),
    //输出圆心(X0,Y0)及圆心角Angle(-360~360);若三点共线无法形成圆弧返回False, 否则返回True
    function GetArcBy3PointsEx(X1, Y1, X2, Y2, X3, Y3: Double; var X0, Y0, Angle: Double): Boolean;
    //指定起止点及圆心作弧: 输入起止点(X1,Y1)、(X2,Y2)、参考点(X3,Y3)、圆心(X0,Y0),
    //输出圆心角Angle(-360~360);若无法形成圆弧返回False, 否则返回True
    function GetArcByCenter(X1, Y1, X2, Y2, X3, Y3, X0, Y0: Double; var Angle: Double): Boolean;
    //指定起止点及半径作弧: 输入起止点(X1,Y1)、(X2,Y2)、参考点(X3,Y3)、半径Radius,
    //输出圆心(X0,Y0)及圆心角Angle(-360~360);若无法形成圆弧返回False, 否则返回True
    function GetArcByRadius(X1, Y1, X2, Y2, X3, Y3, Radius: Double; var X0, Y0, Angle: Double): Boolean;
    
    //夹角过渡弧1: 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)与圆弧半径r,
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)(切点)、(RX1,RY1)-(RX2,RY2)(切点)与圆心(X0,Y0)
    //若线段无夹角或半径不合适返回False; 否则返回True
    function GetInterimArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, X0, Y0: Double): Boolean;
    //夹角过渡弧2: 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、保留区域标识点(FX,FY)与圆弧半径r,
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)、(RX1,RY1)-(RX2,RY2)与圆心(X0,Y0)
    //若线段无夹角或半径不合适返回False; 否则返回True
    function GetInterimArcEx(X1, Y1, X2, Y2, X3, Y3, X4, Y4, FX, FY, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, X0, Y0: Double): Boolean;
    //夹角弧3(用于MapX): 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)与圆弧半径r,
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)、(RX1,RY1)-(RX2,RY2);
    //(LX2,LY2)-(RX2,RY2)之中点到以(LX2,LY2)、(RX2,RY2)为切点的圆弧切线交点的距离Dist以及夹角常数Angle(90°/270°)
    //若线段无夹角或半径不合适返回False; 否则返回True
    function GetInterimArcMapX(X1, Y1, X2, Y2, X3, Y3, X4, Y4, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, Angle, Dist: Double): Boolean;
    
    
    implementation
    
    //方位角: 输入线段(X1,Y1)-(X2,Y2); 返回方位角
    
    function GetLineAngle(X1, Y1, X2, Y2: Double): Double;
    var
        k: Double;
    begin
        if (X2 = X1) then //垂线
            if (Y2 > Y1) then
                Result := 90
            else
                Result := 270
        else
        begin
            k := (Y2 - Y1) / (X2 - X1);
            k := ArcTan(k) * 180 / Pi;
            if X2 < X1 then //二、三象限
                Result := k + 180
            else if Y2 >= Y1 then //一象限
                Result := k
            else //四象限
                Result := k + 360;
        end;
    end;
    
    //长度: 输入线段(X1,Y1)-(X2,Y2); 返回长度
    
    function GetLineLength(X1, Y1, X2, Y2: Double): Double;
    begin
        Result := Sqrt(Sqr(X2 - X1) + Sqr(Y2 - Y1));
    end;
    
    //顺时针角度: 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3); 返回True(顺时针)或False(逆时针)
    
    function IsClockwise(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    var
        angle1, angle2: Double;
    begin
        angle1 := GetLineAngle(X2, Y2, X1, Y1);
        angle2 := GetLineAngle(X2, Y2, X3, Y3);
        if angle2 < angle1 then
            angle2 := angle2 + 360;
        Result := (angle2 - angle1 >= 180);
    end;
    
    //顺时针: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 返回True(顺时针)或False(逆时针)
    
    function IsClockwiseEx(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Boolean;
    var
        angle1, angle2: Double;
    begin
        angle1 := GetLineAngle(X1, Y1, X2, Y2);
        angle2 := GetLineAngle(X3, Y3, X4, Y4);
        if angle2 < angle1 then
            angle2 := angle2 + 360;
        Result := (angle2 - angle1 >= 180);
    end;
    
    //点到直线距离: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 返回距离
    
    function GetVertDist(X1, Y1, X2, Y2, X3, Y3: Double): Double;
    var
        k: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then //线段端点重合
            Result := GetLineLength(X1, Y1, X3, Y3)
        else
        begin
            k := GetLineLength(X1, Y1, X2, Y2);
            Result := Abs((Y2 - Y1) * (X3 - X1) - (X2 - X1) * (Y3 - Y1)) / k;
        end;
    end;
    
    //垂足: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 输出垂足(X,Y)
    
    procedure GetVertXY(X1, Y1, X2, Y2, X3, Y3: Double; var X, Y: Double);
    var
        k: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then
        begin
            X := X1;
            Y := Y1;
        end
        else
        begin
            k := Sqr(X2 - X1) + Sqr(Y2 - Y1);
            X := (Sqr(Y2 - Y1) * X1 + Sqr(X2 - X1) * X3 + (Y2 - Y1) * (Y3 - Y1) * (X2 - X1)) / k;
            Y := (Sqr(X2 - X1) * Y1 + Sqr(Y2 - Y1) * Y3 + (Y2 - Y1) * (X3 - X1) * (X2 - X1)) / k;
        end;
    end;
    
    //线段端点(X2,Y2)处垂线上指定长度的点
    //输入线段(X1,Y1)-(X2,Y2)、距离d; 输出点(LX,LY)、(RX,RY); 若线段端点重合返回False
    
    function GetVertDistXY(X1, Y1, X2, Y2, d: Double; var LX, LY, RX, RY: Double): Boolean;
    var
        k: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then
            Result := False
        else
        begin
            k := GetLineLength(X1, Y1, X2, Y2);
            LX := X2 + (d * (Y2 - Y1)) / k;
            LY := Y2 - (d * (X2 - X1)) / k;
            RX := X2 - (d * (Y2 - Y1)) / k;
            RY := Y2 + (d * (X2 - X1)) / k;
            Result := True;
        end;
    end;
    
    //线段端点(X2,Y2)方向延长线上指定长度的点
    //输入线段(X1,Y1)-(X2,Y2)、距离d; 输出点(LX,LY)、(RX,RY); 若线段端点重合返回False
    
    function GetExtendDistXY(X1, Y1, X2, Y2, d: Double; var LX, LY, RX, RY: Double): Boolean;
    var
        k: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then
            Result := False
        else
        begin
            k := GetLineLength(X1, Y1, X2, Y2);
            LX := X2 + (d * (X2 - X1)) / k;
            LY := Y2 + (d * (Y2 - Y1)) / k;
            RX := X2 - (d * (X2 - X1)) / k;
            RY := Y2 - (d * (Y2 - Y1)) / k;
            Result := True;
        end;
    end;
    
    //对称点:输入点(X1,Y1)、(X0,Y0); 输出点(X1,Y1)关于(X0,Y0)的对称点
    
    procedure GetSymmetricXY(X1, Y1, X0, Y0: Double; var X, Y: Double);
    begin
        X := X0 * 2 - X1;
        Y := Y0 * 2 - Y1;
    end;
    
    //两直线夹角: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 返回夹角(<180)
    
    function GetIntersectAngle(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Double;
    var
        a, b, angle: Double;
    begin
        a := GetLineAngle(X1, Y1, X2, Y2);
        b := GetLineAngle(X3, Y3, X4, Y4);
        angle := Abs(b - a);
        if angle > 180 then
            Result := 360 - angle
        else
            Result := angle;
    end;
    
    //过点作线段的平行线: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 输出平行线(LX,LY)-(RX,RY); 若线段端点重合返回False
    
    function GetParaLineByPoint(X1, Y1, X2, Y2, X3, Y3: Double; var LX, LY, RX, RY: Double): Boolean;
    var
        tX1, tY1, tX2, tY2: Double;
        d: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then
            Result := False
        else
        begin
            d := GetVertDist(X1, Y1, X2, Y2, X3, Y3);
            GetVertDistXY(X2, Y2, X1, Y1, d, LX, LY, tX1, tY1);
            GetVertDistXY(X1, Y1, X2, Y2, d, tX2, tY2, RX, RY);
            if GetVertDist(LX, LY, RX, RY, X3, Y3) > 0.001 then
            begin
                LX := tX1;
                LY := tY1;
                RX := tX2;
                Ry := tY2;
            end;
            Result := True;
        end;
    end;
    
    //作线段某侧一定距离的平行线: 输入线段(X1,Y1)-(X2,Y2)、距离Dist、位置FlagLeft; 输出平行线(LX,LY)-(RX,RY); 若线段端点重合返回False
    
    function GetParaLineByDist(X1, Y1, X2, Y2, Dist: Double; FlagLeft: Boolean; var LX, LY, RX, RY: Double): Boolean;
    var
        tX1, tY1, tX2, tY2: Double;
        Clockwise: Boolean;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then //端点重合
            Result := False
        else
        begin
            GetVertDistXY(X2, Y2, X1, Y1, Dist, LX, LY, tX1, tY1);
            GetVertDistXY(X1, Y1, X2, Y2, Dist, tX2, tY2, RX, RY);
            Clockwise := IsClockwise(X1, Y1, X2, Y2, RX, RY);
        //左边即(X1,Y1)-(X2,Y2)与平行线上任一点形成的角呈逆时针
            if (FlagLeft and Clockwise) or (not FlagLeft and not Clockwise) then
            begin
                LX := tX1;
                LY := tY1;
                RX := tX2;
                Ry := tY2;
            end;
            Result := True;
        end;
    end;
    
    //作连续线某侧一定距离的平行线: 输入连续线InPts、距离Dist、位置FlagLeft; 输出平行连续线OutPts; 若线段端点重合返回False
    
    function GetParaLineByDistEx(var InPts: uPoints; Dist: Double; FlagLeft: Boolean; var OutPts: uPoints): Boolean;
    var
        X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y: Double;
        i, j, k: Integer;
    begin
            result:=False;
        if Length(InPts) < 2 then //少于两点
            Result := False
        else if (Length(InPts) = 2)
            and (Abs(InPts[1].X - InPts[0].X) < 0.0001) and (Abs(InPts[1].Y - InPts[0].Y) < 0.0001) then //端点重合
            Result := False
        else if Dist < 0 then //间距不合适
            Result := False
        else if Dist < 0.00001 then //复制
        begin
            SetLength(OutPts, Length(InPts));
            for i := 0 to Length(InPts) - 1 do
            begin
                OutPts[i].X := InPts[i].X;
                OutPts[i].y := InPts[i].Y;
            end;
        end
        else //平行线
        begin
        //first paraline
        //顺时针->线段右边的平行线
            GetParaLineByDist(InPts[0].X, InPts[0].Y, InPts[1].X, InPts[1].Y,
                Dist, FlagLeft, X1, Y1, X2, Y2);
            SetLength(OutPts, 2);
            OutPts[0].X := X1;
            OutPts[0].Y := Y1;
            OutPts[1].X := X2;
            OutPts[1].Y := Y2;
        //Other paralines
            for i := 1 to Length(InPts) - 2 do //point
            begin
          //平行线
                GetParaLineByDist(InPts[i].X, InPts[i].Y, InPts[i + 1].X, InPts[i + 1].Y,
                    Dist, FlagLeft, X3, Y3, X4, Y4);
                while True do
                begin
                    X1 := OutPts[Length(OutPts) - 2].X;
                    Y1 := OutPts[Length(OutPts) - 2].Y;
                    X2 := OutPts[Length(OutPts) - 1].X;
                    Y2 := OutPts[Length(OutPts) - 1].Y;
            //交点
                    GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y);
            //交点在(X1, Y1)-(X2, Y2)的反向延长线上?
                    if Abs(GetLineLength(X2, Y2, X1, Y1) + GetLineLength(X1, Y1, X, Y) - GetLineLength(X2, Y2, X, Y)) < 0.0001 then
                    begin
              //舍去线段(X1,Y1)-(X2,Y2)
                        if Length(OutPts) > 2 then
                            SetLength(OutPts, Length(OutPts) - 1)
                        else
                        begin
                            SetLength(OutPts, 2);
                            OutPts[0].X := X3;
                            OutPts[0].Y := Y3;
                            OutPts[1].X := X4;
                            OutPts[1].Y := Y4;
                            break;
                        end;
                    end //反向延长线
                    else
                    begin
              //用交点取代最后点
                        OutPts[Length(OutPts) - 1].X := X;
                        OutPts[Length(OutPts) - 1].Y := Y;
              //交点在(X3, Y3)-(X4, Y4)的正向延长线上?
                        if Abs(GetLineLength(X3, Y3, X4, Y4) + GetLineLength(X4, Y4, X, Y) - GetLineLength(X3, Y3, X, Y)) < 0.0001 then
              //(X3,Y3)关于(X,Y)的对称点(X4,Y4)
                            GetSymmetricXY(X3, Y3, X, Y, X4, Y4);
                        SetLength(OutPts, Length(OutPts) + 1);
                        OutPts[Length(OutPts) - 1].X := X4;
                        OutPts[Length(OutPts) - 1].Y := Y4;
                        break;
                    end;
                end;
            end;
        //封闭区域特别处理
            if (GetLineLength(InPts[0].X, InPts[0].Y, InPts[Length(InPts) - 1].X, InPts[Length(InPts) - 1].Y) < 0.0001)
            and (Length(OutPts) > 3) then
                while Length(OutPts) > 3 do
                begin
                    i := 0;
                    j := Length(OutPts) - 1;
                    X1 := OutPts[i + 1].X;
                    Y1 := OutPts[i + 1].Y;
                    X2 := OutPts[i].X;
                    Y2 := OutPts[i].Y;
                    X3 := OutPts[j - 1].X;
                    Y3 := OutPts[j - 1].Y;
                    X4 := OutPts[j].X;
                    Y4 := OutPts[j].Y;
            //交点
                    GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y);
            //交点在(X1, Y1)-(X2, Y2)的反向延长线上?
                    if Abs(GetLineLength(X2, Y2, X1, Y1) + GetLineLength(X1, Y1, X, Y) - GetLineLength(X2, Y2, X, Y)) < 0.0001 then
              //舍去点(X2,Y2)
                    begin
                        for k := i + 1 to Length(OutPts) - 1 do
                        begin
                            OutPts[k - 1].X := OutPts[k].X;
                            OutPts[k - 1].Y := OutPts[k].Y;
                        end;
                        SetLength(OutPts, Length(OutPts) - 1);
                    end
            //交点在(XX3, YY3)-(XX4, YY4)的反向延长线上?
                    else if Abs(GetLineLength(X4, Y4, X3, Y3) + GetLineLength(X3, Y3, X, Y) - GetLineLength(X4, Y4, X, Y)) < 0.0001 then
              //舍去点(XX4,YY4)
                        SetLength(OutPts, Length(OutPts) - 1)
                    else
                    begin
              //用交点代替首尾节点
                        OutPts[i].X := X;
                        OutPts[i].Y := Y;
                        OutPts[j].X := X;
                        OutPts[j].Y := Y;
                        break;
                    end;
                end;
            Result := (Length(OutPts) >= 2);
        end;
    end;
    
    //作两线段的中心线: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 输出中心线(LX,LY)-(RX,RY); 若线段端点重合返回False
    
    function GetCentreline(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double; var LX, LY, RX, RY: Double): Boolean;
    var
        tX1, tY1, tX2, tY2: Double;
        d: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then
            Result := False
        else
        begin
            d := GetIntersectAngle(X1, Y1, X2, Y2, X3, Y3, X4, Y4);
            if d > 90 then
            begin
                tX1 := (X1 + X4) / 2;
                tY1 := (Y1 + Y4) / 2;
                tX2 := (X2 + X3) / 2;
                tY2 := (Y2 + Y3) / 2;
            end
            else
            begin
                tX1 := (X1 + X3) / 2;
                tY1 := (Y1 + Y3) / 2;
                tX2 := (X2 + X4) / 2;
                tY2 := (Y2 + Y4) / 2;
            end;
            LX := tX1;
            LY := tY1;
            RX := tX2;
            Ry := tY2;
            Result := True;
        end;
    end;
    
    //判断两直线有无交点: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 若两线段有交点返回True
    
    function IsLineIntersect(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double): Boolean;
    var
        k1, k2: Double;
        X, Y: Double;
    begin
        if ((Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001)
            or (Abs(X4 - X3) < 0.0001) and (Abs(Y4 - Y3) < 0.0001)) then //有一线段端点重合
            Result := False
        else if (X2 = X1) and (X4 = X3) then //平行
            Result := False
        else
        begin
            if (X2 = X1) then
            begin
                k2 := (Y4 - Y3) / (X4 - X3);
                X := X1;
                Y := k2 * (X - X3) + Y3;
            end
            else if (X4 = X3) then
            begin
                k1 := (Y2 - Y1) / (X2 - X1);
                X := X3;
                Y := k1 * (X - X1) + Y1;
            end
            else
            begin
                k1 := (Y2 - Y1) / (X2 - X1);
                k2 := (Y4 - Y3) / (X4 - X3);
                if k1 = k2 then //平行
                begin
                    Result := False;
                    exit;
                end
                else
                begin
                    X := (Y4 - k2 * X4 - Y2 + k1 * X2) / (k1 - k2);
                    Y := (k1 * (Y4 - k2 * X4) - k2 * (Y2 - k1 * X2)) / (k1 - k2);
                end;
            end;
        //交点是否在线段上
            Result := (GetLineLength(X, Y, X1, Y1) + GetLineLength(X, Y, X2, Y2) - GetLineLength(X1, Y1, X2, Y2) < 0.0001)
                and (GetLineLength(X, Y, X3, Y3) + GetLineLength(X, Y, X4, Y4) - GetLineLength(X3, Y3, X4, Y4) < 0.0001);
        end;
    end;
    
    //两直线交点: 输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4); 输出交点(X,Y); 若两线段平行返回False
    
    function GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Double; var X, Y: Double): Boolean;
    var
        k1, k2: Double;
    begin
        if ((Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001)
            or (Abs(X4 - X3) < 0.0001) and (Abs(Y4 - Y3) < 0.0001)) then //有一线段端点重合
            Result := False
        else if (X2 = X1) and (X4 = X3) then //平行
            Result := False
        else if (X2 = X1) then
        begin
            k2 := (Y4 - Y3) / (X4 - X3);
            X := X1;
            Y := k2 * (X - X3) + Y3;
            Result := True;
        end
        else if (X4 = X3) then
        begin
            k1 := (Y2 - Y1) / (X2 - X1);
            X := X3;
            Y := k1 * (X - X1) + Y1;
            Result := True;
        end
        else
        begin
            k1 := (Y2 - Y1) / (X2 - X1);
            k2 := (Y4 - Y3) / (X4 - X3);
            if k1 = k2 then //平行
                Result := False
            else
            begin
                X := (Y4 - k2 * X4 - Y2 + k1 * X2) / (k1 - k2);
                Y := (k1 * (Y4 - k2 * X4) - k2 * (Y2 - k1 * X2)) / (k1 - k2);
                Result := True;
            end;
        end;
    end;
    
    //作线段的参考线: 输入线段(X1,Y1)-(X2,Y2)、角度(-360~360); 输出与已知线段成已知角度的线段的另一端点(X,Y); 若线段端点重合返回False
    
    function GetAngleLine(X1, Y1, X2, Y2: Double; angle: Double; var X, Y: Double): Boolean;
    var
        d, angle1: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then //线段端点重合
            Result := False
        else
        begin
            d := GetLineLength(X1, Y1, X2, Y2);
            angle1 := (GetLineAngle(X1, Y1, X2, Y2) + angle) * Pi / 180;
            X := X1 + d * Cos(angle1);
            Y := Y1 + d * Sin(angle1);
            Result := True;
        end;
    end;
    
    //点在直线内侧: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 若点在线段内侧返回True,否则返回False
    
    function IsPointInsideLine(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    var
    //  a13, a23, a: Double;
        X0, Y0: Double;
    begin
        if (Abs(X2 - X1) < 0.0001) and (Abs(Y2 - Y1) < 0.0001) then //端点重合
            if (Abs(X3 - X1) < 0.0001) and (Abs(Y3 - Y1) < 0.0001) then //重合
                Result := True
            else
                Result := False
        else
        begin
            GetVertXY(X1, Y1, X2, Y2, X3, Y3, X0, Y0);
            Result := ((X0 >= Min(X1, X2)) and (X0 <= Max(X1, X2))
                and (Y0 >= Min(Y1, Y2)) and (Y0 <= Max(Y1, Y2)));
        {a13 := GetIntersectAngle(X1,Y1,X2,Y2,X1,Y1,X3,Y3);
        a23 := GetIntersectAngle(X2,Y2,X1,Y1,X2,Y2,X3,Y3);
        if (a13<=90) and (a23<=90) then
          Result := True
        else
          Result := False;}
        end;
    end;
    
    //点在直线上: 输入线段(X1,Y1)-(X2,Y2)、点(X3,Y3); 若点在线段上返回True,否则返回False
    
    function IsPointOnLine(X1, Y1, X2, Y2, X3, Y3: Double): Boolean;
    var
        d13, d23, d: Double;
    begin
        d13 := GetLineLength(X1, Y1, X3, Y3);
        d23 := GetLineLength(X2, Y2, X3, Y3);
        d := GetLineLength(X1, Y1, X2, Y2);
        Result := (Abs(d13 + d23 - d) < 0.0001);
    end;
    
    //点在相交区域:输入线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、点(X,Y); 输出点所在相交区域的端点(X0,Y0)、(LX,LY)、(RX,RY)
    //若线段相交返回True,否则返回False
    
    function GetIntersectRegion(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y: Double; var X0, Y0, LX, LY, RX, RY: Double): Boolean;
    begin
      //交点
        if not GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X0, Y0) then
            Result := False
        else
        begin
        //交点与端点重合
            if GetLineLength(X0, Y0, X2, Y2) < 0.00001 then
            begin LX := X1; LY := Y1; end
            else if GetLineLength(X0, Y0, X1, Y1) < 0.00001 then
            begin LX := X2; LY := Y2; end
        //交点在延长线上
            else if Abs(GetLineAngle(X0, Y0, X1, Y1) - GetLineAngle(X0, Y0, X2, Y2)) < 0.001 then
                if GetLineLength(X1, Y1, X0, Y0) > GetLineLength(X2, Y2, X0, Y0) then
                begin LX := X1; LY := Y1; end
                else
                begin LX := X2; LY := Y2; end
        //指示点在哪个相交区域
            else if IsClockwise(X3, Y3, X4, Y4, X, Y) = IsClockwise(X3, Y3, X4, Y4, X1, Y1) then
            begin LX := X1; LY := Y1; end
            else
            begin LX := X2; LY := Y2; end;
        //交点与端点重合
            if GetLineLength(X0, Y0, X4, Y4) < 0.00001 then
            begin RX := X3; RY := Y3; end
            else if GetLineLength(X0, Y0, X3, Y3) < 0.00001 then
            begin RX := X4; RY := Y4; end
        //交点在延长线上
            else if Abs(GetLineAngle(X0, Y0, X3, Y3) - GetLineAngle(X0, Y0, X4, Y4)) < 0.001 then
                if GetLineLength(X3, Y3, X0, Y0) > GetLineLength(X4, Y4, X0, Y0) then
                begin RX := X3; RY := Y3; end
                else
                begin RX := X4; RY := Y4; end
        //指示点在哪个相交区域
            else if IsClockwise(X1, Y1, X2, Y2, X, Y) = IsClockwise(X1, Y1, X2, Y2, X3, Y3) then
            begin RX := X3; RY := Y3; end
            else
            begin RX := X4; RY := Y4; end;
            Result := True;
        end;
    end;
    
    //梯形顶点:输入方向线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、给定面积A;
    //输出梯形顶点(LX1,LY1)、(LX2,LY2)和(RX1,RY1)、(RX2,RY2), 若梯形存在返回True,否则返回False
    
    function GetTrapezoidNodes(X1, Y1, X2, Y2, X3, Y3, X4, Y4, A: Double;
        var LX1, LY1, RX1, RY1, LX2, LY2, RX2, RY2: Double): Boolean;
    var
        angle1, angle2: Double;
        h, d, v: Double;
        Clockwise: Boolean;
        X, Y: Double;
    begin
        A := Abs(A);
        if (Abs(X4 - X2) < 0.0001) and (Abs(Y4 - Y2) < 0.0001) then //端点重合
        begin
            Result := False;
            exit;
        end;
      //方向角
        angle1 := GetIntersectAngle(X1, Y1, X2, Y2, X2, Y2, X4, Y4);
        angle2 := GetIntersectAngle(X3, Y3, X4, Y4, X4, Y4, X2, Y2);
      //底边长
        d := GetLineLength(X2, Y2, X4, Y4);
        if (angle1 = 0) or (angle2 = 0) then
            Result := False
        else if (angle1 = 90) and (angle2 = 90) then
        begin
            h := A / d;
        //底边端点处垂线上点
            GetVertDistXY(X2, Y2, X4, Y4, h, LX2, LY2, RX2, RY2);
            GetVertDistXY(X4, Y4, X2, Y2, h, RX1, RY1, LX1, LY1);
            Result := True;
        end
        else
        begin
            if (angle2 = 90) then
                v := 1 / Tan(angle1 * Pi / 180)
            else if (angle1 = 90) then
                v := 1 / Tan(angle2 * Pi / 180)
            else
                v := 1 / Tan(angle1 * Pi / 180) + 1 / Tan(angle2 * Pi / 180);
        //相邻线段交点
            if GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y) then
          //底线与交点形成角的方向:顺时针?
                Clockwise := IsClockwise(X2, Y2, X4, Y4, X, Y)
            else
                Clockwise := True;
        //方案一:vh*h-2dh+2a=0求解
            if d * d - 2 * v * A < 0 then
            begin
                LX1 := X2; LY1 := Y2;
                RX1 := X4; RY1 := Y4;
            end
            else
            begin
          //梯形高度
                h := (d - Sqrt(d * d - 2 * v * A)) / v;
          //平行线
                GetParaLineByDist(X2, Y2, X4, Y4, h, not Clockwise, LX1, LY1, RX1, RY1);
          //平行线与相邻线段的交点
                GetIntersectXY(X1, Y1, X2, Y2, LX1, LY1, RX1, RY1, LX1, LY1);
                GetIntersectXY(X3, Y3, X4, Y4, LX1, LY1, RX1, RY1, RX1, RY1);
          //梯形是否有效?
                if Abs((d + GetLineLength(LX1, LY1, RX1, RY1)) * h / 2 - A) > 0.1 then
                begin
            //平行线
                    GetParaLineByDist(X2, Y2, X4, Y4, h, Clockwise, LX1, LY1, RX1, RY1);
            //平行线与相邻线段的交点
                    GetIntersectXY(X1, Y1, X2, Y2, LX1, LY1, RX1, RY1, LX1, LY1);
                    GetIntersectXY(X3, Y3, X4, Y4, LX1, LY1, RX1, RY1, RX1, RY1);
                end;
            end;
        //方案二:vh*h+2dh-2a=0求解
            if d * d + 2 * v * A < 0 then
            begin
                LX2 := X2; LY2 := Y2;
                RX2 := X4; RY2 := Y4;
            end
            else
            begin
          //梯形高度
                h := (-d + Sqrt(d * d + 2 * v * A)) / v;
          //平行线
                GetParaLineByDist(X2, Y2, X4, Y4, h, Clockwise, LX2, LY2, RX2, RY2);
          //平行线与相邻线段的交点
                GetIntersectXY(X1, Y1, X2, Y2, LX2, LY2, RX2, RY2, LX2, LY2);
                GetIntersectXY(X3, Y3, X4, Y4, LX2, LY2, RX2, RY2, RX2, RY2);
          //梯形是否有效?
                if Abs((d + GetLineLength(LX2, LY2, RX2, RY2)) * h / 2 - A) > 0.1 then
                begin
            //平行线
                    GetParaLineByDist(X2, Y2, X4, Y4, h, not Clockwise, LX2, LY2, RX2, RY2);
            //平行线与相邻线段的交点
                    GetIntersectXY(X1, Y1, X2, Y2, LX2, LY2, RX2, RY2, LX2, LY2);
                    GetIntersectXY(X3, Y3, X4, Y4, LX2, LY2, RX2, RY2, RX2, RY2);
                end;
            end;
            Result := True;
        end;
    end;
    
    //三角形重心(垂直平分线交点): 输入点(X1,Y1)、(X2,Y2)、(X3,Y3), 若不在一直线上输出重心(X,Y),返回True,否则返回False
    
    function GetWeightCenter(X1, Y1, X2, Y2, X3, Y3: Double; var X, Y: Double): Boolean;
    begin
        if GetVertDist(X1, Y1, X3, Y3, X2, Y2) < 0.0001 then //三点在一直线
            Result := False
        else
        begin
            X := ((Y2 - Y1) * (Y3 - Y2) * (Y1 - Y3) - (Y2 - Y1) * (X3 * X3 - X1 * X1) + (Y3 - Y1) * (X2 * X2 - X1 * X1)) / 2 / ((Y3 - Y1) * (X2 - X1) - (X3 - X1) * (Y2 - Y1));
            Y := ((X2 - X1) * (X3 - X2) * (X1 - X3) - (X2 - X1) * (Y3 * Y3 - Y1 * Y1) + (X3 - X1) * (Y2 * Y2 - Y1 * Y1)) / 2 / ((X3 - X1) * (Y2 - Y1) - (Y3 - Y1) * (X2 - X1));
            Result := True;
        end;
    end;
    
    //过三点作弧1: 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3),
    //输出(X1,Y1)-(X3,Y3)之中点到以(X1,Y1)、(X3,Y3)为切点的圆弧切线交点的距离Dist以及夹角常数Angle(90°/270°)
    //若三点共线无法形成圆弧返回False, 否则返回True
    
    function GetArcBy3PointsMapX(X1, Y1, X2, Y2, X3, Y3: Double; var Angle, Dist: Double): Boolean;
    var
        X0, Y0: Double; //重心
        XX, YY: Double; //(X1,Y1)-(X3,Y3)之中点
    begin
        if GetWeightCenter(X1, Y1, X3, Y3, X2, Y2, X0, Y0) then
        begin
            if IsClockwise(X1, Y1, X3, Y3, X2, Y2) then
                Angle := 270
            else
                Angle := 90;
            XX := (X1 + X3) / 2;
            YY := (Y1 + Y3) / 2;
            Dist := GetLineLength(X0, Y0, XX, YY);
            if Dist = 0 then
                Dist := 1.3946
            else
                Dist := GetLineLength(X1, Y1, XX, YY) / Dist / 2 * 1.3946;
    //    Dist := (GetLineLength(X0, Y0, X2, Y2)-GetLineLength(X0, Y0, XX, YY))/GetLineLength(X1, Y1, X3, Y3);
            Result := True;
        end
        else
            Result := False
    end;
    
    //过三点作弧2(折线成弧): 输入三点(X1,Y1)、(X2,Y2)、(X3,Y3),
    //输出圆心(X0,Y0)及圆心角Angle(-360~360);若三点共线无法形成圆弧返回False, 否则返回True
    
    function GetArcBy3PointsEx(X1, Y1, X2, Y2, X3, Y3: Double; var X0, Y0, Angle: Double): Boolean;
    var
        Clockwise0, Clockwise: Boolean;
    begin
      //有重心
        if GetWeightCenter(X1, Y1, X2, Y2, X3, Y3, X0, Y0) then
        begin
        //<180的圆心角
            Angle := GetIntersectAngle(X1, Y1, X0, Y0, X3, Y3, X0, Y0);
        //圆心角顺时针?
            Clockwise0 := IsClockwise(X1, Y1, X0, Y0, X3, Y3);
        //顶角顺时针?
            Clockwise := IsClockwise(X1, Y1, X2, Y2, X3, Y3);
        //>180的弧
            if (Clockwise0 = Clockwise) then
                Angle := 360 - Angle;
        //递减
            if ((Angle < 180) and Clockwise0) or ((Angle >= 180) and not Clockwise0) then
                Angle := -Angle;
            Result := True;
        end
        else
            Result := False;
    end;
    
    //指定起止点及圆心作弧: 输入起止点(X1,Y1)、(X2,Y2)、参考点(X3,Y3)、圆心(X0,Y0),
    //输出圆心角Angle(-360~360);若无法形成圆弧返回False, 否则返回True
    
    function GetArcByCenter(X1, Y1, X2, Y2, X3, Y3, X0, Y0: Double; var Angle: Double): Boolean;
    var
        Clockwise0, Clockwise: Boolean;
    begin
        if (GetLineLength(X0, Y0, X1, Y1) > 0.00001)
            and (GetLineLength(X0, Y0, X2, Y2) > 0.00001)
            and (GetLineLength(X1, Y1, X2, Y2) > 0.00001)
            and (GetLineLength(X2, Y2, X3, Y3) > 0.00001)
            and (GetLineLength(X1, Y1, X3, Y3) > 0.00001) then
        begin
        //弧度
            Angle := GetLineAngle(X0, Y0, X2, Y2) - GetLineAngle(X0, Y0, X1, Y1);
        //圆心角顺时针?
            Clockwise0 := IsClockwise(X1, Y1, X0, Y0, X2, Y2);
        //参考点决定弧度
            Clockwise := IsClockwise(X1, Y1, X3, Y3, X2, Y2);
        //圆心与参考点不在起止点连线的同一侧时取小弧;反之,取大弧
            if ((Clockwise0 = Clockwise) = (Abs(Angle) <= 180)) then
                if Angle > 0 then
                    Angle := Angle - 360
                else
                    Angle := 360 + Angle;
            Result := True;
        end
        else
            Result := False;
    end;
    
    //指定起止点及半径作弧: 输入起止点(X1,Y1)、(X2,Y2)、参考点(X3,Y3)、半径Radius,
    //输出圆心(X0,Y0)及圆心角Angle(-360~360);若无法形成圆弧返回False, 否则返回True
    
    function GetArcByRadius(X1, Y1, X2, Y2, X3, Y3, Radius: Double; var X0, Y0, Angle: Double): Boolean;
    var
        X, Y, XX0, YY0: Double;
        d, Angle0: Double;
        Clockwise0, Clockwise: Boolean;
        SmallArc: Boolean;
    begin
        if (Radius > 0)
            and (GetLineLength(X1, Y1, X2, Y2) > 0.00001)
            and (GetLineLength(X2, Y2, X3, Y3) > 0.00001)
            and (GetLineLength(X1, Y1, X3, Y3) > 0.00001) then
        begin
        //取中点
            X := (X1 + X2) / 2;
            Y := (Y1 + Y2) / 2;
        //中点到圆心距离
            if Radius - GetLineLength(X1, Y1, X, Y) > 0 then
            begin
                d := Sqrt(Radius * Radius - Sqr(GetLineLength(X1, Y1, X, Y)));
          //圆心
                GetVertDistXY(X1, Y1, X, Y, d, X0, Y0, XX0, YY0);
          //弧度
                Angle := GetLineAngle(X0, Y0, X2, Y2) - GetLineAngle(X0, Y0, X1, Y1);
                Angle0 := GetLineAngle(XX0, YY0, X2, Y2) - GetLineAngle(XX0, YY0, X1, Y1);
          //圆心角顺时针?
                Clockwise0 := IsClockwise(X1, Y1, X0, Y0, X2, Y2);
          //参考点决定圆心与弧度
                Clockwise := IsClockwise(X1, Y1, X3, Y3, X2, Y2);
          //参考点在起止点连线内侧且垂距小于Radius-d时取小弧
                SmallArc := IsPointInsideLine(X1, Y1, X2, Y2, x3, Y3)
                    and (GetVertDist(X1, Y1, X2, Y2, X3, Y3) < Radius - d);
          //取小弧时,圆心与参考点不在同一侧;反之,圆心与参考点在同一侧
                if (SmallArc = (Clockwise0 = Clockwise)) then
                begin
                    X0 := XX0; Y0 := YY0;
                    Angle := Angle0;
                end;
          //真实弧度
                if SmallArc = (Abs(Angle) > 180) then
                    if Angle > 0 then
                        Angle := Angle - 360
                    else
                        Angle := 360 + Angle;
                Result := True;
            end
            else
                Result := False;
        end
        else
            Result := False;
    end;
    
    //夹角过渡弧1: 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)与圆弧半径r(若线段有交点,默认保留较长的端点),
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)、(RX1,RY1)-(RX2,RY2)与圆心(X0,Y0)
    //若线段无夹角或半径不合适返回False; 否则返回True
    
    function GetInterimArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, X0, Y0: Double): Boolean;
    var
        X, Y: Double; //交点
        Angle: Double; //夹角/2
        h: Double; //边线上切点到交点距离
        tmpX, tmpY: Double;
    begin
        if (r <= 0) or not GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y) then //平行
            Result := False
        else
        begin
            if GetLineLength(X1, Y1, X, Y) > GetLineLength(X2, Y2, X, Y) then //保留点
            begin LX1 := X1; LY1 := Y1; end
            else
            begin LX1 := X2; LY1 := Y2; end;
            if GetLineLength(X3, Y3, X, Y) > GetLineLength(X4, Y4, X, Y) then
            begin RX1 := X3; RY1 := Y3; end
            else
            begin RX1 := X4; RY1 := Y4; end;
            Angle := GetIntersectAngle(LX1, LY1, X, Y, RX1, RY1, X, Y) / 2 / 180 * Pi; //夹角
            h := r / Tan(Angle); //边线上切点到交点距离
            GetExtendDistXY(LX1, LY1, X, Y, h, tmpX, tmpY, LX2, LY2); //(LX2,LY2)延长线上点(切点)
            GetExtendDistXY(RX1, RY1, X, Y, h, tmpX, tmpY, RX2, RY2); //(RX2,RY2)
            GetVertDistXY(X, Y, LX2, LY2, r, tmpX, tmpY, X0, Y0); //(X0,Y0)圆弧中心点
            if Abs(GetLineLength(tmpX, tmpY, RX2, RY2) - r) < 0.0001 then
            begin X0 := tmpX; Y0 := tmpY; end;
    
            Result := True;
        end;
    end;
    
    //夹角过渡弧2: 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)、保留区域标识点(FX,FY)与圆弧半径r,
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)、(RX1,RY1)-(RX2,RY2)与圆心(X0,Y0)
    //若线段无夹角或半径不合适返回False; 否则返回True
    
    function GetInterimArcEx(X1, Y1, X2, Y2, X3, Y3, X4, Y4, FX, FY, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, X0, Y0: Double): Boolean;
    var
        X, Y: Double; //交点
        Angle: Double; //夹角/2
        h: Double; //边线上切点到交点距离
        tmpX, tmpY: Double;
    begin
        if (r <= 0) or not GetIntersectRegion(X1, Y1, X2, Y2, X3, Y3, X4, Y4, FX, FY, X, Y, LX1, LY1, RX1, RY1) then //平行
            Result := False
        else
        begin
            Angle := GetIntersectAngle(LX1, LY1, X, Y, RX1, RY1, X, Y) / 2 / 180 * Pi; //夹角
            h := r / Tan(Angle); //边线上切点到交点距离
            GetExtendDistXY(LX1, LY1, X, Y, h, tmpX, tmpY, LX2, LY2); //(LX2,LY2)延长线上点(切点)
            GetExtendDistXY(RX1, RY1, X, Y, h, tmpX, tmpY, RX2, RY2); //(RX2,RY2)
            GetVertDistXY(X, Y, LX2, LY2, r, tmpX, tmpY, X0, Y0); //(X0,Y0)圆弧中心点
            if Abs(GetLineLength(tmpX, tmpY, RX2, RY2) - r) < 0.0001 then
            begin X0 := tmpX; Y0 := tmpY; end;
    
            Result := True;
        end;
    end;
    
    //夹角弧3: 输入两线段(X1,Y1)-(X2,Y2)、(X3,Y3)-(X4,Y4)与圆弧半径r,
    //输出延长/截断的两线段(LX1,LY1)-(LX2,LY2)、(RX1,RY1)-(RX2,RY2);
    //(LX2,LY2)-(RX2,RY2)之中点到以(LX2,LY2)、(RX2,RY2)为切点的圆弧切线交点的距离Dist以及夹角常数Angle(90°/270°)
    //若线段无夹角或半径不合适返回False; 否则返回True
    
    function GetInterimArcMapX(X1, Y1, X2, Y2, X3, Y3, X4, Y4, r: Double;
        var LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, Angle, Dist: Double): Boolean;
    var
        X0, Y0: Double; //圆弧中心
        X, Y: Double; //直线交点
        XX, YY: Double; //(LX2,LY2)-(RX2,RY2)之中点
    begin
        if GetInterimArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4, r, LX1, LY1, LX2, LY2, RX1, RY1, RX2, RY2, X0, Y0) then
        begin
            GetIntersectXY(X1, Y1, X2, Y2, X3, Y3, X4, Y4, X, Y);
            if IsClockwise(LX2, LY2, RX2, RY2, X, Y) then
                Angle := 270
            else
                Angle := 90;
            XX := (LX2 + RX2) / 2;
            YY := (LY2 + RY2) / 2;
            Dist := r - GetLineLength(X0, Y0, XX, YY);
            Result := True;
        end
        else
            Result := False
    end;
    
    end.
  • 相关阅读:
    HDU3371--Connect the Cities
    HDU1232--畅通工程
    HDU1102--Constructing Roads
    HDU1856--More is better
    HDU1325--Is It A Tree?
    HDU1272--小希的迷宫
    HDU1213--How Many Tables
    lnmp 实现owncloud
    lemp 编译安装 不完整版
    dns 视图
  • 原文地址:https://www.cnblogs.com/gisoracle/p/14277653.html
Copyright © 2011-2022 走看看