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

📄 graphmath.pas

📁 这是图形处理中常用的数学计算方法。比较全面
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  Result := not RE(a, b, Err) and (a < b);
end;

function RG(const a, b: Double; Err: Double = ERROR7): Boolean;
begin
  Result := not RE(a, b, Err) and (a > b);
end;

function RLE(const a, b: Double; Err: Double = ERROR7): Boolean;
begin
  Result := (a < b) or RE(a, b, Err);
end;

function RGE(const a, b: Double; Err: Double = ERROR7): Boolean;
begin
  Result := (a > b) or RE(a, b, Err);
end;

{两变量是否相同}

function VarEqual(const A, B: Variant): Boolean;
begin
  Result := (VarType(A) = VarType(B)) and (A = B);
end;

{两点是否相同}

function IsSamePoint(const x1, y1, x2, y2: Double; Err: Double = ERROR7): Boolean;
begin
  Result := (Abs(x1 - x2) < Err) and (Abs(y1 - y2) < Err);
end;

function IsSamePoint(const Pnt1, Pnt2: TRealPoint; Err: Double = ERROR7): Boolean;
begin
  Result := IsSamePoint(Pnt1.x, Pnt1.y, Pnt2.x, Pnt2.y, Err);
end;

{两边是否相同}

function IsSameEdge(const pEdge1, pEdge2: pPolygonEdge; Err: Double = ERROR7): Boolean;
begin
  Result := True;

  if (pEdge1.pPolyArc = nil) and (pEdge2.pPolyArc <> nil) or
    (pEdge1.pPolyArc <> nil) and (pEdge2.pPolyArc = nil) then
    Result := False
  else
  begin //同为弧或线段
    if (not IsSamePoint(pEdge1.sPnt, pEdge2.sPnt, Err)) or (not IsSamePoint(pEdge1.ePnt, pEdge2.ePnt, Err)) then
      Result := False;

    if pEdge1.pPolyArc <> nil then
    begin
      if (pEdge1.pPolyArc.bOutFlag <> pEdge2.pPolyArc.bOutFlag) or
        (not IsSamePoint(pEdge1.pPolyArc.OPnt, pEdge2.pPolyArc.OPnt, Err)) or
        (not RE(pEdge1.pPolyArc.sAng, pEdge2.pPolyArc.sAng, Err)) or
        (not RE(pEdge1.pPolyArc.eAng, pEdge2.pPolyArc.eAng, Err)) or
        (not RE(pEdge1.pPolyArc.R, pEdge2.pPolyArc.R, Err)) then
        Result := False;
    end;
  end;
end;

{两个多边形是否完全一样(重叠)}

function IsSamePolygon(const pPolygon1, pPolygon2: pPolygonRecord; Err: Double = ERROR7): Boolean;
var
  pEdge1, pEdge2: pPolygonEdge;
  FindSameEdge: Boolean;
begin
  Result := False;
  if (pPolygon1.EdgeCount <> pPolygon2.EdgeCount) or
    (pPolygon1.bExistArc <> pPolygon2.bExistArc) then
    exit;

  pEdge1 := pPolygon1.pHeadEdge;
  pEdge2 := pPolygon2.pHeadEdge;

  //在pPolygon2找到和pPolygon1头边一样的边
  FindSameEdge := False;
  while pEdge2 <> nil do
  begin
    if IsSameEdge(pEdge1, pEdge2, Err) then
    begin
      FindSameEdge := True;
      break;
    end;
    pEdge2 := pEdge2.pEdgeNext;
  end;
  if not FindSameEdge then
    Exit;

  //比较其余对应边是否一样
  while (pEdge1.pEdgeNext <> nil) and (pEdge1.pEdgeNext <> pPolygon1.pHeadEdge) do
  begin
    pEdge1 := pEdge1.pEdgeNext;
    if pEdge2.pEdgeNext = nil then
      pEdge2 := pPolygon2.pHeadEdge
    else
      pEdge2 := pEdge2.pEdgeNext;

    if not IsSameEdge(pEdge1, pEdge2, Err) then
      Exit;
  end;

  Result := True;
end;

{一个角是否在另两个角之间; Ang, Ang1, Ang2 = [0..4*pi)}

function BetweenAngle(Ang, Ang1, Ang2: TRadian; Err: Double = ERROR7): Boolean;
begin
  Ang := NormalRadian(Ang);
  Ang1 := NormalRadian(Ang1);
  Ang2 := NormalRadian(Ang2);
  MinToMax(Ang1, Ang2);
  Result := RGE(Ang, Ang1, Err) and RLE(Ang, Ang2, Err);
end;

{一值是否在另两值之间}

function BetweenValue(const Val, Val1, Val2: Double; Err: Double = ERROR7): Boolean;
begin
  Result := RGE(Val, min(Val1, Val2), Err) and RLE(Val, max(Val1, Val2), Err);
end;

{判断点是否在直线上}

function PointOnLine(const x, y: Double; const BLine: TBeeLine; Err: Double = ERROR7): Boolean;
begin
  Result := DisPointLine(x, y, BLine) < Err;  
end;

function PointOnLine(const x, y: Double; const BLine: TSecLine; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnLine(x, y, BeeLine(BLine), Err);
end;

function PointOnLine(const Pnt, Pnt1, Pnt2: TRealPoint; Err: Double = ERROR7): Boolean; //点dPnt-直线(dPnt1dPnt2构成的)
begin
  Result := PointOnLine(Pnt.x, Pnt.y, BeeLine(Pnt1, Pnt2), Err);
end;

function PointOnLine(const Pnt: TRealPoint; pEdge: pPolygonEdge; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnLine(Pnt, pEdge.sPnt, pEdge.ePnt, Err);
end;

{判断点是否在线段上}

function PointOnSeg(const x, y, x1, y1, x2, y2: Double; Err: Double = ERROR7): Boolean;
begin
  Result := False;
  if not PointOnLine(x, y, BeeLine(x1, y1, x2, y2), Err) then
    Exit;

  if BetweenValue(x, x1, x2, Err) and BetweenValue(y, y1, y2, Err) then
    Result := True;
end;

function PointOnSeg(const x, y: Double; const lineS: TSecLine; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnSeg(x, y, lines.x1, lines.y1, lines.x2, lines.y2, Err);
end;

function PointOnSeg(const P: TRealPoint; const lineS: TSecLine; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnSeg(P.x, P.y, lineS, Err);
end;

function PointOnSeg(const dPnt, dPnt1, dPnt2: TRealPoint; Err: Double = ERROR7): Boolean;
var
  ASecLine: TSecLine;
begin
  ASecLine := SecLine(dPnt1, dPnt2);
  Result := PointOnSeg(dPnt, ASecLine, Err);
end;

function PointOnSeg(const dPnt: TRealPoint; pEdge: pPolygonEdge; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnSeg(dPnt, pEdge.sPnt, pEdge.ePnt, Err);
end;

{判断点是否在弧线上}

function PointOnArc(const x, y, R: Double; const OPnt: TRealPoint; const sAng, eAng: TRadian; Err: Double = ERROR7): Boolean;
var
  Dis: Double;
  Ang, AngErr: TRadian; //统一角度和距离的误差
  dPnt: TRealPoint;
begin
  Result := False;
  Dis := DisPointPoint(x, y, OPnt.x, OPnt.y);
  if RE(Dis, R, Err) then
  begin
    dPnt.x := x;
    dPnt.y := y;
    Ang := LineAngle(OPnt, dPnt);
    AngErr := Err / R;
    if BetweenAngle(Ang, sAng, eAng, AngErr) then
      Result := True;
  end;
end;

function PointOnArc(x, y: Double; pArc: pPolygonArc; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnArc(x, y, pArc.R, PArc.OPnt, PArc.sAng, pArc.eAng, Err);
end;

function PointOnArc(dPnt: TRealPoint; pArc: pPolygonArc; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnArc(dPnt.x, dPnt.y, pArc, Err);
end;

function PointOnArc(x, y: Double; Arc: TCircleArc; Err: Double = ERROR7): Boolean; // 弧(圆心式)
begin
  Result := PointOnArc(x, y, Arc.r, Arc.oPnt, Arc.sAng, Arc.eAng, Err);
end;

function PointOnArc(P: TRealPoint; arc: TCircleArc; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnArc(P.x, P.y, arc, Err);
end;

{判断一点是否在多边形某边上}

function PointOnEdge(const Pnt: TRealPoint; const pEdge: pPolygonEdge; Err: Double = ERROR7): Boolean;
begin
  if pEdge.pPolyArc <> nil then
    Result := PointOnArc(Pnt, pEdge.pPolyArc, Err)
  else
    Result := PointOnSeg(Pnt, pEdge, Err);
end;

{判断点是否在多边形的某边线上}

function PointOnPolygon(const APnt: TRealPoint; const pHeadEdge: pPolygonEdge; Err: Double = ERROR7): Boolean;
var
  pEdge: pPolygonEdge;
  IsOnRim: Boolean;
begin
  Result := True;
  pEdge := pHeadEdge;
  while pEdge <> nil do
  begin
    IsOnRim := PointOnEdge(APnt, pEdge, Err);
    if IsOnRim then
      Exit;
    pEdge := pEdge.pEdgeNext;
  end;
  Result := False;
end;

{判断线段p1p2是否在直线q1q2上}

function SegOnLine(const Pnt1, Pnt2, sPnt, ePnt: TRealPoint; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnLine(Pnt1, ePnt, ePnt, Err) and PointOnLine(Pnt2, sPnt, ePnt, Err);
end;

{判断线段pEdge是否在q1q2构成的直线上}

function SegOnLine(const pEdge: pPolygonEdge; const sPnt, ePnt: TRealPoint; Err: Double = ERROR7): Boolean;
begin
  Result := SegOnLine(pEdge.sPnt, pEdge.ePnt, sPnt, ePnt, Err);
end;

{判断线段dPnt1dPnt2是否在线段dPnt3dPnt4上}

function SegOnSeg(const Pnt1, Pnt2, sPnt, ePnt: TRealPoint; Err: Double = ERROR7): Boolean;
begin
  Result := PointOnSeg(Pnt1, sPnt, ePnt, Err) and PointOnSeg(Pnt2, sPnt, ePnt, Err);
end;

{判断线段L1是否在线段L2上}

function SegOnSeg(const pEdge1, pEdge2: pPolygonEdge; Err: Double = ERROR7): Boolean;
begin
  Result := SegOnSeg(pEdge1.sPnt, pEdge1.ePnt, pEdge2.sPnt, pEdge2.ePnt, Err);
end;

{点是否在圆线附近(可认为圆被选中) }

function PointNearCircle(const x, y, Ox, Oy, r: Double; OffVal: Double): Boolean;
var
  Dis: Double;
begin
  Dis := DisPointPoint(Ox, Oy, x, y);  
  Result := RL(abs(Dis - r), OffVal);
end;

function PointNearArc(const x, y, Ox, Oy, x1, y1, x2, y2: Double; OffVal: Double): Boolean;
var
  R: Double;
  Ang1, Ang2, Ang: Double;
begin
  Result := false;

  R := DisPointPoint(x, y, Ox, Oy);
  if not PointNearCircle(x, y, Ox, Oy, R, OffVal) then Exit;

  Ang1 := LineAngle(Ox, Oy, x1, y1);
  Ang2 := LineAngle(Ox, Oy, x2, y2);
  Ang := LineAngle(Ox, Oy, x, y);
  Result := BetweenAngle(Ang, Ang1, Ang2);
end;

//-------------判断~是否在某区域内--------------((

{点是否在圆内}

function InCircle(const x, y, ox, oy, R: Double; Err: Double = ERROR7): Boolean;
var
  Dis: Double;
begin
  Dis := DisPointPoint(ox, oy, x, y);     //
  Result := RLE(Dis, R, Err);
end;

{点是否在环内}

function InAnnular(const x, y: Double; const Sector: TAnnular; Err: Double = ERROR7): Boolean;
var
  Dis: Double;
  Ang: TRadian;
  ox, oy: Double;
begin
  Result := False;
  ox := Sector.ox;
  oy := Sector.oy;

  Dis := Sqrt(Sqr(ox - x) + Sqr(oy - y));
  if not RGE(Dis, Sector.r1, Err) or not RLE(Dis, Sector.r2, Err) then
    Exit;

  Ang := LineAngle(ox, oy, x, y);
  with Sector do
  begin
    if BetweenAngle(Ang, sAng, eAng, Err) then
      Result := True;
  end;
end;


{点是否在三角形内}

function InTriangle(p, p1, p2, p3: TRealPoint): Boolean;
const
  Err: TRadian = ERROR2; // 相近角度的0.5度
var
  Ang1, Ang2, Ang3: TRadian; //计算角度Ang1(P1_P),Ang2(P2_P),Ang3(P3_P)
  //三个角度有一个大于pi,则说明此点位于三角形(P1_P2_P3)外部
begin
  Result := False;

  Ang1 := LineAngle(P, P1);
  Ang2 := LineAngle(P, P2);
  Ang3 := LineAngle(P, P3);

  // 将三个角度按大小对Ang1,Ang2,Ang3的赋值
  if Ang1 > Ang2 then
    Ang2 := Ang2 + 2 * pi;
  if Ang1 > Ang3 then
    Ang3 := Ang3 + 2 * pi;
  if Ang2 > Ang3 then
    SwapValue(Ang2, Ang3);

  //判断角度是否大于pi,如是则表明此点在三角形外
  if (Ang2 - Ang1) > pi + Err th

⌨️ 快捷键说明

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