• delphi 判断点在多边形内


      1 unit MainFM;
      2 
      3 interface
      4 
      5 uses
      6   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      7   Vcl.Controls, Vcl.Forms, Vcl.Dialogs,utils_dvalue, utils_DValue_JSON, math;
      8 
      9 type
     10   PPos = ^TPos;
     11   TPos = record
     12     x: double;
     13     y: double;
     14   end;
     15   TForm1 = class(TForm)
     16     procedure FormCreate(Sender: TObject);
     17     procedure FormDestroy(Sender: TObject);
     18   private
     19     { Private declarations }
     20     FInfo: TDValue;
     21     min_x, min_y, max_x, max_y: Double;
     22     function in_line(p, a, b: TPos):boolean;
     23     function in_scope(x, y: double):boolean;
     24     function js_scope(x, y: double):boolean;
     25     function get_angle(a, p, b: TPos): Double;
     26     function angle_scope(x, y: double):Boolean;
     27   public
     28     { Public declarations }
     29   end;
     30 
     31 var
     32   Form1: TForm1;
     33 
     34 implementation
     35 
     36 {$R *.dfm}
     37 
     38 const
     39    AREA_JS = '[{"x":25.050192,"y":102.685862},{"x":25.048684,"y":102.679662},{"x":25.046881,"y":102.6795},{"x":25.046794,"y":102.679432},{"x":25.045442,"y":102.679317},{"x":25.045053,"y":102.679703},' +
     40           '{"x":25.044956,"y":102.680877},{"x":25.044077,"y":102.680803},{"x":25.04405,"y":102.68082},{"x":25.043932,"y":102.680812},{"x":25.042992,"y":102.681473},{"x":25.042543,"y":102.680512},' +
     41           '{"x":25.040577,"y":102.680628},{"x":25.040201,"y":102.680619},{"x":25.040199,"y":102.680616},{"x":25.038735,"y":102.680584},{"x":25.038131,"y":102.679581},{"x":25.036289,"y":102.68087},' +
     42           '{"x":25.035543,"y":102.680316},{"x":25.032567,"y":102.682154},{"x":25.030944,"y":102.679494},{"x":25.030683,"y":102.679922},{"x":25.02918,"y":102.678526},{"x":25.020929,"y":102.691384},' +
     43           '{"x":25.018434,"y":102.695194},{"x":25.018199,"y":102.695462},{"x":25.018154,"y":102.695623},{"x":25.014317,"y":102.701847},{"x":25.014257,"y":102.701777},{"x":25.014214,"y":102.701799},' +
     44           '{"x":25.014193,"y":102.701833},{"x":25.013665,"y":102.703895},{"x":25.0135,"y":102.708667},{"x":25.013731,"y":102.711444},{"x":25.013688,"y":102.711598},{"x":25.014635,"y":102.728022},' +
     45           '{"x":25.017457,"y":102.727245},{"x":25.017227,"y":102.727632},{"x":25.017398,"y":102.730491},{"x":25.017994,"y":102.731972},{"x":25.019514,"y":102.734679},{"x":25.019822,"y":102.736062},' +
     46           '{"x":25.021592,"y":102.734747},{"x":25.022972,"y":102.736725},{"x":25.024394,"y":102.739288},{"x":25.025337,"y":102.739351},{"x":25.02553,"y":102.741181},{"x":25.027447,"y":102.741482},' +
     47           '{"x":25.027511,"y":102.740923},{"x":25.027796,"y":102.741078},{"x":25.029644,"y":102.737365},{"x":25.032853,"y":102.737421},{"x":25.032824,"y":102.743083},{"x":25.034417,"y":102.743137},' +
     48           '{"x":25.035607,"y":102.743816},{"x":25.036682,"y":102.741746},{"x":25.038471,"y":102.743515},{"x":25.040554,"y":102.744645},{"x":25.041723,"y":102.744501},{"x":25.042272,"y":102.743377},' +
     49           '{"x":25.041406,"y":102.741458},{"x":25.041972,"y":102.740368},{"x":25.043552,"y":102.739007},{"x":25.044843,"y":102.737357},{"x":25.045317,"y":102.737367},{"x":25.045394,"y":102.737643},' +
     50           '{"x":25.046456,"y":102.737673},{"x":25.046487,"y":102.736363},{"x":25.047268,"y":102.736121},{"x":25.048442,"y":102.736882},{"x":25.049793,"y":102.735303},{"x":25.049454,"y":102.734985},' +
     51           '{"x":25.049949,"y":102.734738},{"x":25.050208,"y":102.73392},{"x":25.049452,"y":102.732817},{"x":25.050428,"y":102.731672},{"x":25.051611,"y":102.730455},{"x":25.052832,"y":102.731477},' +
     52           '{"x":25.053183,"y":102.730854},{"x":25.055187,"y":102.728466},{"x":25.055845,"y":102.729135},{"x":25.057024,"y":102.727607},{"x":25.057807,"y":102.726003},{"x":25.059392,"y":102.720135},' +
     53           '{"x":25.059951,"y":102.72017},{"x":25.062027,"y":102.721034},{"x":25.062385,"y":102.72006},{"x":25.063003,"y":102.720215},{"x":25.063863,"y":102.717103},{"x":25.062979,"y":102.716844},' +
     54           '{"x":25.063065,"y":102.715942},{"x":25.062657,"y":102.715496},{"x":25.062696,"y":102.715054},{"x":25.062367,"y":102.714957},{"x":25.062725,"y":102.713192},{"x":25.061683,"y":102.713097},' +
     55           '{"x":25.061665,"y":102.712598},{"x":25.060553,"y":102.712448},{"x":25.060689,"y":102.710459},{"x":25.061079,"y":102.708519},{"x":25.061649,"y":102.707398},{"x":25.06164,"y":102.706604},' +
     56           '{"x":25.060134,"y":102.706413},{"x":25.060187,"y":102.704655},{"x":25.06047,"y":102.704099},{"x":25.060271,"y":102.702606},{"x":25.061233,"y":102.702174},{"x":25.062926,"y":102.702057},' +
     57           '{"x":25.063063,"y":102.700747},{"x":25.062848,"y":102.698117},{"x":25.062557,"y":102.698149},{"x":25.062526,"y":102.697755},{"x":25.062375,"y":102.697764},{"x":25.062467,"y":102.697104},' +
     58           '{"x":25.062128,"y":102.696998},{"x":25.062086,"y":102.696072},{"x":25.060061,"y":102.696191},{"x":25.05891,"y":102.695299},{"x":25.058661,"y":102.694585},{"x":25.058814,"y":102.693901},' +
     59           '{"x":25.059055,"y":102.69348},{"x":25.059847,"y":102.692906},{"x":25.05932,"y":102.691352},{"x":25.059009,"y":102.69107},{"x":25.058361,"y":102.691324},{"x":25.058288,"y":102.692227},' +
     60           '{"x":25.058544,"y":102.69323},{"x":25.057257,"y":102.693822},{"x":25.055803,"y":102.694269},{"x":25.053974,"y":102.6905},{"x":25.053752,"y":102.690326},{"x":25.053012,"y":102.690614},' +
     61           '{"x":25.052192,"y":102.690245},{"x":25.052909,"y":102.687701},{"x":25.052385,"y":102.685977},{"x":25.051531,"y":102.686171},{"x":25.051377,"y":102.686717},{"x":25.050672,"y":102.686137},' +
     62           '{"x":25.050192,"y":102.685862}]';
     63 
     64 procedure TForm1.FormCreate(Sender: TObject);
     65 var
     66   i: Integer;
     67   x, y: double;
     68 begin
     69   FInfo := TDValue.Create(vntArray);
     70   JSONParser(AREA_JS, FInfo);
     71   //计算最大最小值
     72   min_x := FInfo.Items[0].ForceByName('x').AsFloat;
     73   min_y := FInfo.Items[0].ForceByName('y').AsFloat;
     74   max_x := min_x; max_y := min_y;
     75   for i := 1 to FInfo.Count - 1 do
     76   begin
     77     x := FInfo.Items[i].ForceByName('x').AsFloat;
     78     y := FInfo.Items[i].ForceByName('y').AsFloat;
     79     if min_x > x then min_x := x;
     80     if min_y > y then min_y := y;
     81     if max_x < x then max_x := x;
     82     if max_y < y then max_y := y;
     83   end;
     84   x := 25.035571963033; y := 102.71040295303;
     85   x := 25.06574; y := 102.69685;
     86   x := 25.032819; y:= 102.744553;
     87   if in_scope(x,y) then showmessage('在区域内')
     88   else showmessage('不在区域内');
     89 end;
     90 
     91 procedure TForm1.FormDestroy(Sender: TObject);
     92 begin
     93   FInfo.Free;
     94 end;
     95 
     96 function TForm1.in_line(p, a, b: TPos):Boolean;
     97 var
     98   minx,miny,maxx, maxy, a1, a2, tmp: double;
     99 begin
    100     minx := a.x; if minx > b.x then minx := b.x;
    101     miny := a.y; if miny > b.y then miny := b.y;
    102     maxx := a.x; if maxx < b.x then maxx := b.x;
    103     maxy := a.y; if maxy < b.y then maxy := b.y;
    104     if (p.x >= minx) and (p.y >= miny) and (p.x <= maxx) and (p.y <= maxy) then
    105     begin
    106        a1 := (a.x - p.x)*(b.y - p.y);
    107        a2 := (b.x - p.x)*(a.y - p.y);
    108        tmp := a1 - a2;
    109        if tmp < 0 then tmp := a2 - a1;
    110        Result := tmp < 0.0001;
    111     end else begin
    112       Result := false;
    113     end;
    114 end;
    115 
    116 function TForm1.get_angle(a, p, b: TPos): Double;
    117 var
    118   pa, pb, ab, apb: Double;
    119 begin
    120   pa := (a.x - p.x)*(a.x - p.x) + (a.y - p.y)* (a.y - p.y);
    121   pb := (b.x - p.x)*(b.x - p.x) + (b.y - p.y)* (b.y - p.y);
    122   ab := (b.x - a.x)*(b.x - a.x) + (b.y - a.y)* (b.y - a.y);
    123 
    124   apb := pa + pb - ab;
    125 
    126   pa := sqrt(pa);
    127   pb := sqrt(pb);
    128   apb := apb / (2 * pa * pb);
    129   REsult := ArcCos(apb);
    130 end;
    131 
    132 function TForm1.angle_scope(x, y: double):Boolean;
    133 var
    134   i,k: Integer;
    135   d1, d2: TDValue;
    136   p, p1, p2: TPos;
    137   angle: double;
    138 begin
    139   k := 1000;
    140   p.x := x * k;
    141   p.y := y * k;
    142   for i := 0 to FInfo.Count - 1 do
    143   begin
    144     d1 := FInfo.Items[i];
    145     d2 := FInfo.Items[(i + 1) mod FInfo.Count];
    146     p1.x := d1.ForceByName('x').AsFloat * k;
    147     p1.y := d1.ForceByName('y').AsFloat * k;
    148     p2.x := d2.ForceByName('x').AsFloat * k;
    149     p2.y := d2.ForceByName('y').AsFloat * k;
    150     if in_line(p, p1, p2) then
    151     begin
    152       Result := True;
    153       exit;
    154     end;
    155     angle := angle + get_angle(p1, p, p2);
    156   end;
    157   angle := angle - PI * 2;
    158   if angle < 0 then angle := -1 * angle;
    159   Result := angle < 0.0001;
    160 end;
    161 
    162 function TForm1.in_scope(x, y: double):boolean;
    163 var
    164   i,cross: Integer;
    165   d1, d2: TDValue;
    166   p, p1, p2: TPos;
    167   y1, y2, tmp, tmpx: double;
    168 begin
    169   cross := 0;
    170   p.x := x;
    171   p.y := y;
    172   for i := 0 to FInfo.Count - 1 do
    173   begin
    174     d1 := FInfo.Items[i];
    175     d2 := FInfo.Items[(i + 1) mod FInfo.Count];
    176     p1.x := d1.ForceByName('x').AsFloat;  p1.y := d1.ForceByName('y').AsFloat;
    177     p2.x := d2.ForceByName('x').AsFloat;  p2.y := d2.ForceByName('y').AsFloat;
    178 
    179     if in_line(p, p1, p2) then
    180     begin
    181       cross := 1;
    182       break;
    183     end;
    184     if p1.y = p2.y then continue;
    185     y1 := p1.y;
    186     y2 := p2.y;
    187     if y1 > y2 then
    188     begin
    189       y1 := p2.y;
    190       y2 := p1.y;
    191     end;
    192     if p.y < y1 then continue;
    193     if p.y > y2 then continue;
    194 
    195     tmpx := (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
    196     (*
    197     tmp := p.x - tmpx;
    198     if tmp < 0 then tmp := tmpx - p.x;
    199     if tmp < 0.0001 then
    200     begin
    201       cross := 1;
    202       break;
    203     end;
    204     tmp := p1.y - p.y;
    205     if tmp < 0 then tmp := p.y - p1.y;
    206     if tmp < 0.0001 then
    207     begin
    208         if( (min_y = p1.y) or (max_y = p1.y) ) and (p.x< p1.x ) then
    209         begin
    210           cross := 0;
    211           break;
    212         end;
    213         continue;
    214     end;
    215     *)
    216     if(tmpx > p.x) then cross := cross + 1;
    217   end; // end of for
    218   Result := (cross mod 2) = 1
    219 end;
    220 
    221 function TForm1.js_scope(x, y: double):boolean;
    222 var
    223   i,j: Integer;
    224   d1,d2: TDValue;
    225   xi,yi,xj,yj: Single;
    226 begin
    227   Result := False;
    228   j := FInfo.Count - 1;
    229   for i := 0 to FInfo.Count - 1 do
    230   begin
    231     d1 := FInfo.Items[i];
    232     d2 := FInfo.Items[j];
    233     j := i;
    234     xi := d1.ForceByName('x').AsFloat;
    235     yi := d1.ForceByName('y').AsFloat;
    236     xj := d2.ForceByName('x').AsFloat;
    237     yj := d2.ForceByName('y').AsFloat;
    238     if( (yi > y) <> (yj > y) ) and ( x < ((xj - xi) * (y - yi) / (yj - yi) + xi) ) then
    239       Result := not Result;
    240   end;
    241 end;
    242 
    243 end.
  • 相关阅读:
    如何带平均年龄小的团队
    如何带平均年龄大的团队
    Extjs中常用表单介绍与应用
    .NET 应用架构指导 V2[17]
    一个男人的关心的东西
    微软企业库5.0学习笔记(十四)
    .NET 应用架构指导 V2[19]
    微软企业库5.0学习笔记(十五)
    计算机基本图书
    vs添加博客园精华区
  • 原文地址:https://www.cnblogs.com/btxz/p/12992698.html
Copyright © 2020-2023  润新知