W
wk_knife
Unregistered / Unconfirmed
GUEST, unregistred user!
共一个端点的两条线段,各有分在两侧的一定距离H的平行线,这四条平行线相交出四个交点。如何判断四个交点中哪个点在线段所夹的方向。
具体见下图,也就是找到实线段所夹的红色点。
http://www.delphibbs.com/keylife/images/u81530/未命名.bmp
我现在的办法是先通过y=A*X+B
得出平行线的PB:=B +(or -) H/cos(arctg(A));
再得到四个角点。
一开始我觉得只要判断四个点中有哪个点落到线段构成的三角形中就可以了,后来发现这个想法是错误的。如果线段很短,就不会有任一个点落到这个三角形中。
下面是现在的代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
P0,P1,P2,px1,px2,px3,px4:TPoint;
sum:integer;
function GetAB(pA,pB:TPoint;var A,B
ouble):Boolean;
procedure GetABParaDeltaB(pA,pB,pC:TPoint;H
ouble);
end;
var
Form1: TForm1;
implementation
uses Math;
{$R *.dfm}
function TForm1.GetAB(pA, pB: TPoint; var A, B: Double):Boolean;
begin
result:=False;
if pA.x <>pB.x then
begin
A:=(pB.Y-pA.Y)/(pB.X-pA.X);
B:=pA.y-A*PA.X;
result:=True;
end;
end;
procedure TForm1.GetABParaDeltaB(pA,pB,pC:TPoint;H
ouble);
var
A,B,R,C,D,RP
ouble;
First,Second:Boolean;
ARgn:HRgn;
AA:array of TPoint;
InRgn:integer;
begin
canvas.MoveTo(PA.X, pA.Y);
Canvas.LineTo(pB.X ,pB.Y);
Canvas.LineTo(pC.X ,pC.Y);
First:=GetAB(pA,pB,A,B);
if First then
R:=H/cos(ArcTan(A));
Second:=GetAB(pB,pC,C,D);
if Second then
RP:=H/cos(ArcTan(C));
SetLength(AA,3);
AA[0]:=pA;
AA[1]:=pB;
AA[2]:=pC;
ARgn:=CreatePolygonRgn(AA[0],3,WINDING);
pX1.X:=Round((d-rp-b+r)/(a-c)); //-r-r'
px1.Y:=Round(a*px1.X+B-r);
if PtInRegion(ARgn,pX1.X,px1.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px1.X-2,px1.Y-2,px1.X+2,px1.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=1;
end
else
Canvas.Rectangle(px1.X-2,px1.Y-2,px1.X+2,px1.Y+2);
pX2.X:=Round((d+rp-b+r)/(a-c)); //-r+r'
px2.Y:=Round(a*px2.X+B-r);
if PtInRegion(ARgn,pX2.X,px2.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px2.X-2,px2.Y-2,px2.X+2,px2.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=2;
end
else
Canvas.Rectangle(px2.X-2,px2.Y-2,px2.X+2,px2.Y+2);
pX3.X:=Round((d-rp-b-r)/(a-c)); //+r-r'
px3.Y:=Round(a*px3.X+B+r);
if PtInRegion(ARgn,pX3.X,px3.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px3.X-2,px3.Y-2,px3.X+2,px3.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=3;
end
else
Canvas.Rectangle(px3.X-2,px3.Y-2,px3.X+2,px3.Y+2);
pX4.X:=Round((d+rp-b-r)/(a-c)); //+r+r'
px4.Y:=Round(a*px4.X+B+r);
if PtInRegion(ARgn,pX4.X,px4.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px4.X-2,px4.Y-2,px4.X+2,px4.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=4;
end
else
Canvas.Rectangle(px4.X-2,px4.Y-2,px4.X+2,px4.Y+2);
DeleteObject(ARgn);
case InRgn of //
1,4: begin
canvas.MoveTo(Px1.X, px1.Y);
Canvas.LineTo(px4.X ,px4.Y);
end;
2,3:begin
canvas.MoveTo(Px2.X, px2.Y);
Canvas.LineTo(px3.X ,px3.Y);
end ;
end; // case
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
sum:=0;
DoubleBuffered:=True;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Pen.Color :=clBlack;
case sum of //
1: Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
2: begin
Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
Canvas.Rectangle(p1.X-2,p1.Y-2,p1.X+2,p1.Y+2);
end;
3: begin
Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
Canvas.Rectangle(p1.X-2,p1.Y-2,p1.X+2,p1.Y+2);
Canvas.Rectangle(p2.X-2,p2.Y-2,p2.X+2,p2.Y+2);
GetABParaDeltaB(p0,p1,p2,20);
end;
end; // case
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inc(Sum);
case sum of //
1,4:begin
Sum:=1;
P0:=Point(x,y);
end;
2: P1:=Point(x,y);
3: P2:=Point(x,y);
end;
invalidate;
end;
end.
具体见下图,也就是找到实线段所夹的红色点。
http://www.delphibbs.com/keylife/images/u81530/未命名.bmp
我现在的办法是先通过y=A*X+B
得出平行线的PB:=B +(or -) H/cos(arctg(A));
再得到四个角点。
一开始我觉得只要判断四个点中有哪个点落到线段构成的三角形中就可以了,后来发现这个想法是错误的。如果线段很短,就不会有任一个点落到这个三角形中。
下面是现在的代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
P0,P1,P2,px1,px2,px3,px4:TPoint;
sum:integer;
function GetAB(pA,pB:TPoint;var A,B
![Big Grin :D :D](https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f600.png)
procedure GetABParaDeltaB(pA,pB,pC:TPoint;H
![Big Grin :D :D](https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f600.png)
end;
var
Form1: TForm1;
implementation
uses Math;
{$R *.dfm}
function TForm1.GetAB(pA, pB: TPoint; var A, B: Double):Boolean;
begin
result:=False;
if pA.x <>pB.x then
begin
A:=(pB.Y-pA.Y)/(pB.X-pA.X);
B:=pA.y-A*PA.X;
result:=True;
end;
end;
procedure TForm1.GetABParaDeltaB(pA,pB,pC:TPoint;H
![Big Grin :D :D](https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f600.png)
var
A,B,R,C,D,RP
![Big Grin :D :D](https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f600.png)
First,Second:Boolean;
ARgn:HRgn;
AA:array of TPoint;
InRgn:integer;
begin
canvas.MoveTo(PA.X, pA.Y);
Canvas.LineTo(pB.X ,pB.Y);
Canvas.LineTo(pC.X ,pC.Y);
First:=GetAB(pA,pB,A,B);
if First then
R:=H/cos(ArcTan(A));
Second:=GetAB(pB,pC,C,D);
if Second then
RP:=H/cos(ArcTan(C));
SetLength(AA,3);
AA[0]:=pA;
AA[1]:=pB;
AA[2]:=pC;
ARgn:=CreatePolygonRgn(AA[0],3,WINDING);
pX1.X:=Round((d-rp-b+r)/(a-c)); //-r-r'
px1.Y:=Round(a*px1.X+B-r);
if PtInRegion(ARgn,pX1.X,px1.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px1.X-2,px1.Y-2,px1.X+2,px1.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=1;
end
else
Canvas.Rectangle(px1.X-2,px1.Y-2,px1.X+2,px1.Y+2);
pX2.X:=Round((d+rp-b+r)/(a-c)); //-r+r'
px2.Y:=Round(a*px2.X+B-r);
if PtInRegion(ARgn,pX2.X,px2.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px2.X-2,px2.Y-2,px2.X+2,px2.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=2;
end
else
Canvas.Rectangle(px2.X-2,px2.Y-2,px2.X+2,px2.Y+2);
pX3.X:=Round((d-rp-b-r)/(a-c)); //+r-r'
px3.Y:=Round(a*px3.X+B+r);
if PtInRegion(ARgn,pX3.X,px3.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px3.X-2,px3.Y-2,px3.X+2,px3.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=3;
end
else
Canvas.Rectangle(px3.X-2,px3.Y-2,px3.X+2,px3.Y+2);
pX4.X:=Round((d+rp-b-r)/(a-c)); //+r+r'
px4.Y:=Round(a*px4.X+B+r);
if PtInRegion(ARgn,pX4.X,px4.Y) then begin
Canvas.Pen.Color:=clRed;
Canvas.Rectangle(px4.X-2,px4.Y-2,px4.X+2,px4.Y+2);
Canvas.Pen.Color:=clBlack;
InRgn:=4;
end
else
Canvas.Rectangle(px4.X-2,px4.Y-2,px4.X+2,px4.Y+2);
DeleteObject(ARgn);
case InRgn of //
1,4: begin
canvas.MoveTo(Px1.X, px1.Y);
Canvas.LineTo(px4.X ,px4.Y);
end;
2,3:begin
canvas.MoveTo(Px2.X, px2.Y);
Canvas.LineTo(px3.X ,px3.Y);
end ;
end; // case
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
sum:=0;
DoubleBuffered:=True;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Pen.Color :=clBlack;
case sum of //
1: Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
2: begin
Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
Canvas.Rectangle(p1.X-2,p1.Y-2,p1.X+2,p1.Y+2);
end;
3: begin
Canvas.Rectangle(p0.X-2,p0.Y-2,p0.X+2,p0.Y+2);
Canvas.Rectangle(p1.X-2,p1.Y-2,p1.X+2,p1.Y+2);
Canvas.Rectangle(p2.X-2,p2.Y-2,p2.X+2,p2.Y+2);
GetABParaDeltaB(p0,p1,p2,20);
end;
end; // case
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inc(Sum);
case sum of //
1,4:begin
Sum:=1;
P0:=Point(x,y);
end;
2: P1:=Point(x,y);
3: P2:=Point(x,y);
end;
invalidate;
end;
end.