zoukankan      html  css  js  c++  java
  • 多边形切割折线

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Security.Cryptography;
      5 using System.Text;
      6 using System.Windows;
      7 using System.Windows.Media;
      8 using System.Windows.Shapes;
      9 
     10 namespace geometry
     11 {
     12     public partial class Help
     13     {
     14 
     15         #region 线段与多边形的交点集合,按从p1到p2的方向进行排序
     16         /// <summary>
     17         /// 对一线段与多边形的交点集合,按从p1到p2的方向进行排序
     18         /// </summary>
     19         /// <param name="p1"></param>
     20         /// <param name="p2"></param>
     21         /// <param name="interPoints"></param>
     22         /// <returns></returns>
     23         public List<Point> SortPointsBySlopeOfLine(Point p1, Point p2, List<Point> interPoints)
     24         {
     25             List<Point> points = new List<Point>();
     26             List<Point> newInterPoints = new List<Point>();
     27             points.Add(p1);
     28             if (Equals(p1.X, p2.X))//垂直线段
     29             {
     30                 if (p1.Y > p2.Y)
     31                 {
     32                     newInterPoints = interPoints.OrderByDescending(t => t.Y).ToList();
     33                 }
     34                 else
     35                 {
     36                     newInterPoints = interPoints.OrderBy(t => t.Y).ToList();
     37                 }
     38             }
     39             else
     40             {
     41                 if (Equals(p1.Y, p2.Y))//水平线段
     42                 {
     43                     if (p1.X > p2.X)
     44                     {
     45                         newInterPoints = interPoints.OrderByDescending(t => t.X).ToList();
     46                     }
     47                     else
     48                     {
     49                         newInterPoints = interPoints.OrderBy(t => t.X).ToList();
     50                     }
     51 
     52                 }
     53                 else//普通斜率线段,按x或y都行
     54                 {
     55                     if (p1.X > p2.X)
     56                     {
     57                         newInterPoints = interPoints.OrderByDescending(t => t.X).ToList();
     58                     }
     59                     else
     60                     {
     61                         newInterPoints = interPoints.OrderBy(t => t.X).ToList();
     62                     }
     63 
     64                 }
     65 
     66             }
     67 
     68             foreach (Point interPoint in newInterPoints)
     69             {
     70                 points.Add(interPoint);
     71             }
     72             points.Add(p2);
     73             return points;
     74         }
     75         #endregion
     76 
     77 
     78         #region 获取线段和线段的交点
     79 
     80         private double eps = 1e-8;
     81         /// <summary>
     82         /// 判断一个数值是否在误差范围内
     83         /// </summary>
     84         /// <param name="x"></param>
     85         /// <returns></returns>
     86         private bool zero(double x)
     87         {
     88 
     89             return (((x) > 0 ? (x) : -(x)) < eps);
     90         }
     91 
     92 
     93         /// <summary>
     94         /// 计算交叉乘积(P1-P0)x(P2-P0)
     95         /// </summary>
     96         /// <param name="p1"></param>
     97         /// <param name="p2"></param>
     98         /// <param name="p0"></param>
     99         /// <returns></returns>
    100         private double xmult(Point p1, Point p2, Point p0)
    101         {
    102             return (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);
    103         }
    104 
    105         /// <summary>
    106         /// 判点是否在线段上,包括端点
    107         /// </summary>
    108         /// <param name="p"></param>
    109         /// <param name="l1"></param>
    110         /// <param name="l2"></param>
    111         /// <returns></returns>
    112         private bool dot_online_in(Point p, Point l1, Point l2)
    113         {
    114             return zero(xmult(p, l1, l2)) && (l1.X - p.X) * (l2.X - p.X) < eps && (l1.Y - p.Y) * (l2.Y - p.Y) < eps;
    115         }
    116 
    117         /// <summary>
    118         /// 判两点在线段同侧,点在线段上返回0
    119         /// </summary>
    120         /// <param name="p1"></param>
    121         /// <param name="p2"></param>
    122         /// <param name="l1"></param>
    123         /// <param name="l2"></param>
    124         /// <returns></returns>
    125         private bool same_side(Point p1, Point p2, Point l1, Point l2)
    126         {
    127             return xmult(l1, p1, l2) * xmult(l1, p2, l2) > eps;
    128         }
    129 
    130         /// <summary>
    131         /// 判断两直线平行
    132         /// </summary>
    133         /// <param name="u1"></param>
    134         /// <param name="u2"></param>
    135         /// <param name="v1"></param>
    136         /// <param name="v2"></param>
    137         /// <returns></returns>
    138         private bool parallel(Point u1, Point u2, Point v1, Point v2)
    139         {
    140             return zero((u1.X - u2.X) * (v1.Y - v2.Y) - (v1.X - v2.X) * (u1.Y - u2.Y));
    141         }
    142 
    143         /// <summary>
    144         /// 判三点共线
    145         /// </summary>
    146         /// <param name="p1"></param>
    147         /// <param name="p2"></param>
    148         /// <param name="p3"></param>
    149         /// <returns></returns>
    150         private bool dots_inline(Point p1, Point p2, Point p3)
    151         {
    152             return zero(xmult(p1, p2, p3));
    153         }
    154 
    155         /// <summary>
    156         /// 判两线段相交,包括端点和部分重合
    157         /// </summary>
    158         /// <param name="u1"></param>
    159         /// <param name="u2"></param>
    160         /// <param name="v1"></param>
    161         /// <param name="v2"></param>
    162         /// <returns></returns>
    163         private bool intersect_in(Point u1, Point u2, Point v1, Point v2)
    164         {
    165             if (!dots_inline(u1, u2, v1) || !dots_inline(u1, u2, v2))
    166                 return !same_side(u1, u2, v1, v2) && !same_side(v1, v2, u1, u2);
    167             return dot_online_in(u1, v1, v2) || dot_online_in(u2, v1, v2) || dot_online_in(v1, u1, u2) || dot_online_in(v2, u1, u2);
    168         }
    169 
    170         /// <summary>
    171         /// 计算两线段交点,请判线段是否相交(同时还是要判断是否平行!)
    172         /// </summary>
    173         /// <param name="u1"></param>
    174         /// <param name="u2"></param>
    175         /// <param name="v1"></param>
    176         /// <param name="v2"></param>
    177         /// <param name="ret"></param>
    178         /// <returns></returns>
    179         private int GetIntersectionPoint(Point u1, Point u2, Point v1, Point v2, out Point ret)
    180         {
    181             ret = u1;
    182             if (parallel(u1, u2, v1, v2) || !intersect_in(u1, u2, v1, v2))
    183             {
    184                 return 0;
    185             }
    186             double t = ((u1.X - v1.X) * (v1.Y - v2.Y) - (u1.Y - v1.Y) * (v1.X - v2.X))
    187               / ((u1.X - u2.X) * (v1.Y - v2.Y) - (u1.Y - u2.Y) * (v1.X - v2.X));
    188             ret.X += (u2.X - u1.X) * t;
    189             ret.Y += (u2.Y - u1.Y) * t;
    190             return 1;
    191         }
    192         #endregion
    193 
    194 
    195         #region 多边形包含点
    196         /// <summary>
    197         /// 判断多边形是否包含某个点
    198         /// </summary>
    199         /// <param name="poly">多边形边框上每个角的点坐标数组</param>
    200         /// <param name="p">要进行判断的点</param>
    201         /// <returns>true:包含; false:不包含</returns>
    202         public bool InPoly(Polygon polygon, Point p)
    203         {
    204 
    205             Point[] poly = polygon.Points.ToArray();
    206             int i = 0, f = 0;
    207             double xi = 0, a = 0, b = 0, c = 0;
    208             Point ps, pe;
    209             ///遍历每一个点
    210             for (i = 0; i <= Microsoft.VisualBasic.Information.UBound(poly, 1); i++)
    211             {
    212                 ps = poly[i];
    213                 if (i < Microsoft.VisualBasic.Information.UBound(poly, 1))
    214                 {
    215                     pe = poly[i + 1];
    216                 }
    217                 else
    218                 {
    219                     pe = poly[0];
    220                 }
    221                 GetStdLine(ps, pe, ref a, ref b, ref c);
    222                 if (a != 0)
    223                 {
    224                     xi = 0 - ((b * p.Y + c) / a);
    225                     if (xi == p.X)
    226                     {
    227                         return true;
    228                     }
    229                     else if (xi < p.X)
    230                     {
    231                         f = f + Sgn(pe.Y - p.Y) - Sgn(ps.Y - p.Y);
    232                     }
    233                 }
    234             }
    235             return f != 0;
    236         }
    237 
    238         /// <summary>
    239         /// 根据两个点的坐标求经过两点的直线的标准方程参数A、B、C
    240         /// </summary>
    241         /// <param name="ps"></param>
    242         /// <param name="pe"></param>
    243         /// <param name="a"></param>
    244         /// <param name="b"></param>
    245         /// <param name="c"></param>
    246         private void GetStdLine(Point ps, Point pe, ref double a, ref double b, ref double c)
    247         {
    248             double xs, ys, xe, ye;
    249             double p1, p2;
    250             xs = ps.X;
    251             ys = ps.Y;
    252             xe = pe.X;
    253             ye = pe.Y;
    254             p1 = (xs * ye);
    255             p2 = (xe * ys);
    256             if (p1 == p2)
    257             {
    258                 if (xs == 0)
    259                 {
    260                     if (xe == 0)
    261                     {
    262                         a = 1;
    263                         b = 0;
    264                         c = 0;
    265                     }
    266                     else if (ys == 0)
    267                     {
    268                         a = ye;
    269                         b = 0 - xe;
    270                         c = 0;
    271                     }
    272                 }
    273                 else if (ye == 0)
    274                 {
    275                     if (ys == 0)
    276                     {
    277                         a = 0;
    278                         b = 1;
    279                         c = 0;
    280                     }
    281                     else if (xe == 0)
    282                     {
    283                         a = 0 - ys;
    284                         b = xs;
    285                         c = 0;
    286                     }
    287                 }
    288             }
    289             else
    290             {
    291                 a = (ys - ye) / (p1 - p2);
    292                 c = 1;
    293                 if (ys == 0)
    294                 {
    295                     if (ye == 0)
    296                     {
    297                         b = 1;
    298                         c = 0;
    299                     }
    300                     else
    301                     {
    302                         b = 0 - ((a * xe + 1) / ye);
    303                     }
    304                 }
    305                 else
    306                 {
    307                     b = 0 - ((a * xs + 1) / ys);
    308                 }
    309             }
    310         }
    311         private int Sgn(double a)
    312         {
    313             if (a == 0)
    314             {
    315                 return 0;
    316             }
    317             else if (a < 0)
    318             {
    319                 return -1;
    320             }
    321             else
    322             {
    323                 return 1;
    324             }
    325         }
    326 
    327         #endregion
    328 
    329         /// <summary>
    330         /// 求出线段和多边形的交点,不包括p1p2
    331         /// </summary>
    332         /// <param name="p1"></param>
    333         /// <param name="p2"></param>
    334         /// <param name="polygon"></param>
    335         /// <returns></returns>
    336         public List<Point> GetInterPoints(Point p1, Point p2, Polygon polygon)
    337         {
    338             List<Point> interPoints = new List<Point>();
    339             List<Point> polygonPoints = polygon.Points.ToList();
    340             for (int i = 0; i < polygonPoints.Count; i++)
    341             {
    342                 Point polygon1 = polygonPoints[i];
    343                 Point polygon2 = new Point();
    344                 if (i == polygonPoints.Count - 1)
    345                 {
    346                     polygon2 = polygonPoints[0];
    347                 }
    348                 else
    349                 {
    350                     polygon2 = polygonPoints[i + 1];
    351 
    352                 }
    353                 Point inter = new Point();
    354                 int interType = GetIntersectionPoint(p1, p2, polygon1, polygon2, out inter);
    355                 switch (interType)
    356                 {
    357 
    358                     case 1:
    359 
    360                         if (!Equals(inter, p1) && !Equals(inter, p2))
    361                         {
    362                             interPoints.Add(inter);
    363                         }
    364                         break;
    365                     case 0:
    366                     default:
    367                         break;
    368                 }
    369             }
    370             return interPoints;
    371         }
    372 
    373         /// <summary>
    374         /// 取两个点的中点
    375         /// </summary>
    376         /// <param name="p1"></param>
    377         /// <param name="p2"></param>
    378         /// <returns></returns>
    379         public Point GetCenter(Point p1, Point p2)
    380         {
    381             return new Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
    382         }
    383 
    384         /// <summary>
    385         /// 获取多边形裁剪折线形成的线段集合
    386         /// </summary>
    387         /// <param name="polyline"></param>
    388         /// <param name="polygon"></param>
    389         /// <returns></returns>
    390         public List<Polyline> GetInterPolylines(Polyline polyline, Polygon polygon)
    391         {
    392             List<Polyline> list = new List<Polyline>();
    393             //TODO: 1.遍历折线上的每相邻的两个个点,组成线段,与多边形的每一条边计算,求出此线段与多边形的边的交点
    394             //TODO:  2.对此线段的上的交点进行排序,组成连续点的折线,判断这些线段在多边形内部的部分,加入集合
    395 
    396             List<Point> polinePoints = polyline.Points.ToList();
    397             List<Point> polygonPoints = polygon.Points.ToList();
    398 
    399             for (int i = 0; i < polinePoints.Count - 1; i++)
    400             {
    401                 Point one = polinePoints[i];
    402                 Point two = new Point();
    403                 if (i == polinePoints.Count - 1)
    404                 {
    405 
    406                 }
    407                 else
    408                 {
    409                     two = polinePoints[i + 1];
    410                 }
    411                 List<Point> inters = GetInterPoints(one, two, polygon);
    412                 List<Point> sortInters = SortPointsBySlopeOfLine(one, two, inters);
    413 
    414                 for (int j = 0; j < sortInters.Count; j++)
    415                 {
    416                     if (j < sortInters.Count - 1)
    417                     {
    418                         if (InPoly(polygon, GetCenter(sortInters[j], sortInters[j + 1])))
    419                         {
    420                             Polyline interPolyline = new Polyline();
    421                             interPolyline.Points.Add(sortInters[j]);
    422                             interPolyline.Points.Add(sortInters[j + 1]);
    423                             list.Add(interPolyline);
    424                         }
    425                     }
    426 
    427                 }
    428             }
    429             return list;
    430         }
    431     }
    432 }
    View Code
  • 相关阅读:
    ValidateRequest问题
    通过反射得到object[]数组的类型并且的到此类型所有的字段及字段的值
    正则表达式匹配括号中的字符,不包括括号
    C# String
    C# TYPES
    C# History and Future
    Mixing unmanaged C++ and CSharp
    [Tip: property]C#3.0 autoimplemented property
    C#: constant and readonly
    c#:Nullable Types
  • 原文地址:https://www.cnblogs.com/shanranlei/p/4316200.html
Copyright © 2011-2022 走看看