An algorithm for inflating/deflating (offsetting, buffering) polygons

后端 未结 12 1907
醉话见心
醉话见心 2020-11-22 12:58

How would I "inflate" a polygon? That is, I want to do something similar to this:

\"alt

<
相关标签:
12条回答
  • 2020-11-22 13:13

    In the GIS world one uses negative buffering for this task: http://www-users.cs.umn.edu/~npramod/enc_pdf.pdf

    The JTS library should do this for you. See the documentation for the buffer operation: http://tsusiatsoftware.net/jts/javadoc/com/vividsolutions/jts/operation/buffer/package-summary.html

    For a rough overview see also the Developer Guide: http://www.vividsolutions.com/jts/bin/JTS%20Developer%20Guide.pdf

    0 讨论(0)
  • 2020-11-22 13:18

    Sounds to me like what you want is:

    • Starting at a vertex, face anti-clockwise along an adjacent edge.
    • Replace the edge with a new, parallel edge placed at distance d to the "left" of the old one.
    • Repeat for all edges.
    • Find the intersections of the new edges to get the new vertices.
    • Detect if you've become a crossed polygon and decide what to do about it. Probably add a new vertex at the crossing-point and get rid of some old ones. I'm not sure whether there's a better way to detect this than just to compare every pair of non-adjacent edges to see if their intersection lies between both pairs of vertices.

    The resulting polygon lies at the required distance from the old polygon "far enough" from the vertices. Near a vertex, the set of points at distance d from the old polygon is, as you say, not a polygon, so the requirement as stated cannot be fulfilled.

    I don't know if this algorithm has a name, example code on the web, or a fiendish optimisation, but I think it describes what you want.

    0 讨论(0)
  • 2020-11-22 13:18

    One further option is to use boost::polygon - the documentation is somewhat lacking, but you should find that the methods resize and bloat, and also the overloaded += operator, which actually implement buffering. So for example increasing the size of a polygon (or a set of polygons) by some value can be as simple as:

    poly += 2; // buffer polygon by 2
    
    0 讨论(0)
  • 2020-11-22 13:20

    Big thanks to Angus Johnson for his clipper library. There are good code samples for doing the clipping stuff at the clipper homepage at http://www.angusj.com/delphi/clipper.php#code but I did not see an example for polygon offsetting. So I thought that maybe it is of use for someone if I post my code:

        public static List<Point> GetOffsetPolygon(List<Point> originalPath, double offset)
        {
            List<Point> resultOffsetPath = new List<Point>();
    
            List<ClipperLib.IntPoint> polygon = new List<ClipperLib.IntPoint>();
            foreach (var point in originalPath)
            {
                polygon.Add(new ClipperLib.IntPoint(point.X, point.Y));
            }
    
            ClipperLib.ClipperOffset co = new ClipperLib.ClipperOffset();
            co.AddPath(polygon, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
    
            List<List<ClipperLib.IntPoint>> solution = new List<List<ClipperLib.IntPoint>>();
            co.Execute(ref solution, offset);
    
            foreach (var offsetPath in solution)
            {
                foreach (var offsetPathPoint in offsetPath)
                {
                    resultOffsetPath.Add(new Point(Convert.ToInt32(offsetPathPoint.X), Convert.ToInt32(offsetPathPoint.Y)));
                }
            }
    
            return resultOffsetPath;
        }
    
    0 讨论(0)
  • 2020-11-22 13:21

    There are a couple of libraries one can use (Also usable for 3D data sets).

    1. https://github.com/otherlab/openmesh
    2. https://github.com/alecjacobson/nested_cages
    3. http://homepage.tudelft.nl/h05k3/Projects/MeshThickeningProj.htm

    One can also find corresponding publications for these libraries to understand the algorithms in more detail.

    The last one has the least dependencies and is self-contained and can read in .obj files.

    Best wishes, Stephan

    0 讨论(0)
  • 2020-11-22 13:23

    I use simple geometry: Vectors and/or Trigonometry

    1. At each corner find the mid vector, and mid angle. Mid vector is the arithmetic average of the two unit vectors defined by the edges of the corner. Mid Angle is the half of the angle defined by the edges.

    2. If you need to expand (or contract) your polygon by the amount of d from each edge; you should go out (in) by the amount d/sin(midAngle) to get the new corner point.

    3. Repeat this for all the corners

    *** Be careful about your direction. Make CounterClockWise Test using the three points defining the corner; to find out which way is out, or in.

    0 讨论(0)
提交回复
热议问题