mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
added example and explantion to point_in_polygon
This commit is contained in:
parent
e807d0e0d6
commit
47f0c88c4a
2 changed files with 76 additions and 16 deletions
|
@ -1317,8 +1317,7 @@ function polygon_normal(poly) =
|
||||||
// Topics: Geometry, Polygons
|
// Topics: Geometry, Polygons
|
||||||
// Description:
|
// Description:
|
||||||
// This function tests whether the given 2D point is inside, outside or on the boundary of
|
// This function tests whether the given 2D point is inside, outside or on the boundary of
|
||||||
// the specified 2D polygon using either the Nonzero Winding rule or the Even-Odd rule.
|
// the specified 2D polygon.
|
||||||
// See https://en.wikipedia.org/wiki/Nonzero-rule and https://en.wikipedia.org/wiki/Even–odd_rule.
|
|
||||||
// The polygon is given as a list of 2D points, not including the repeated end point.
|
// The polygon is given as a list of 2D points, not including the repeated end point.
|
||||||
// Returns -1 if the point is outside the polygon.
|
// Returns -1 if the point is outside the polygon.
|
||||||
// Returns 0 if the point is on the boundary.
|
// Returns 0 if the point is on the boundary.
|
||||||
|
@ -1326,11 +1325,72 @@ function polygon_normal(poly) =
|
||||||
// The polygon does not need to be simple: it may have self-intersections.
|
// The polygon does not need to be simple: it may have self-intersections.
|
||||||
// But the polygon cannot have holes (it must be simply connected).
|
// But the polygon cannot have holes (it must be simply connected).
|
||||||
// Rounding errors may give mixed results for points on or near the boundary.
|
// Rounding errors may give mixed results for points on or near the boundary.
|
||||||
|
// .
|
||||||
|
// When polygons intersect themselves different definitions exist for determining which points
|
||||||
|
// are inside the polygon. The figure below shows the difference.
|
||||||
|
// OpenSCAD uses the Even-Odd rule when creating polygons, where membership in overlapping regions
|
||||||
|
// depends on how many times they overlap. The Nonzero rule considers point inside the polygon if
|
||||||
|
// the polygon overlaps them any number of times. For more information see
|
||||||
|
// https://en.wikipedia.org/wiki/Nonzero-rule and https://en.wikipedia.org/wiki/Even–odd_rule.
|
||||||
|
// Figure(2D,Med):
|
||||||
|
// a=20*2/3;
|
||||||
|
// b=30*2/3;
|
||||||
|
// ofs = 17*2/3;
|
||||||
|
// curve = [for(theta=[0:10:140]) [a * theta/360*2*PI - b*sin(theta), a-b*cos(theta)-20*2/3]];
|
||||||
|
// path = deduplicate(concat( reverse(offset(curve,r=ofs)),
|
||||||
|
// xflip(offset(curve,r=ofs)),
|
||||||
|
// xflip(reverse(curve)),
|
||||||
|
// curve
|
||||||
|
// ));
|
||||||
|
// left(30){
|
||||||
|
// polygon(path);
|
||||||
|
// color("red")stroke(path, width=1, closed=true);
|
||||||
|
// color("red")back(28)text("Even-Odd", size=5, halign="center");
|
||||||
|
// }
|
||||||
|
// right(30){
|
||||||
|
// dp = decompose_path(path,closed=true);
|
||||||
|
// region(dp);
|
||||||
|
// color("red"){stroke(path,width=1,closed=true);
|
||||||
|
// back(28)text("Nonzero", size=5, halign="center");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// point = The 2D point to check position of.
|
// point = The 2D point to check position of.
|
||||||
// poly = The list of 2D path points forming the perimeter of the polygon.
|
// poly = The list of 2D path points forming the perimeter of the polygon.
|
||||||
// nonzero = The rule to use: true for "Nonzero" rule and false for "Even-Odd" (Default: true )
|
// nonzero = The rule to use: true for "Nonzero" rule and false for "Even-Odd" (Default: true )
|
||||||
// eps = Tolerance in geometric comparisons. Default: `EPSILON` (1e-9)
|
// eps = Tolerance in geometric comparisons. Default: `EPSILON` (1e-9)
|
||||||
|
// Example: With nonzero set to true, we get this result. Green dots are inside the polygon and red are outside:
|
||||||
|
// a=20*2/3;
|
||||||
|
// b=30*2/3;
|
||||||
|
// ofs = 17*2/3;
|
||||||
|
// curve = [for(theta=[0:10:140]) [a * theta/360*2*PI - b*sin(theta), a-b*cos(theta)]];
|
||||||
|
// path = deduplicate(concat( reverse(offset(curve,r=ofs)),
|
||||||
|
// xflip(offset(curve,r=ofs)),
|
||||||
|
// xflip(reverse(curve)),
|
||||||
|
// curve
|
||||||
|
// ));
|
||||||
|
// stroke(path);
|
||||||
|
// pts = [[0,0],[10,0],[0,20]];
|
||||||
|
// for(p=pts){
|
||||||
|
// color(point_in_polygon(p,path)==1 ? "green" : "red")
|
||||||
|
// move(p)circle(r=1, $fn=12);
|
||||||
|
// }
|
||||||
|
// Example: With nonzero set to false, one dot changes color:
|
||||||
|
// a=20*2/3;
|
||||||
|
// b=30*2/3;
|
||||||
|
// ofs = 17*2/3;
|
||||||
|
// curve = [for(theta=[0:10:140]) [a * theta/360*2*PI - b*sin(theta), a-b*cos(theta)]];
|
||||||
|
// path = deduplicate(concat( reverse(offset(curve,r=ofs)),
|
||||||
|
// xflip(offset(curve,r=ofs)),
|
||||||
|
// xflip(reverse(curve)),
|
||||||
|
// curve
|
||||||
|
// ));
|
||||||
|
// stroke(path);
|
||||||
|
// pts = [[0,0],[10,0],[0,20]];
|
||||||
|
// for(p=pts){
|
||||||
|
// color(point_in_polygon(p,path,nonzero=false)==1 ? "green" : "red")
|
||||||
|
// move(p)circle(r=1, $fn=12);
|
||||||
|
// }
|
||||||
function point_in_polygon(point, poly, nonzero=true, eps=EPSILON) =
|
function point_in_polygon(point, poly, nonzero=true, eps=EPSILON) =
|
||||||
// Original algorithms from http://geomalgorithms.com/a03-_inclusion.html
|
// Original algorithms from http://geomalgorithms.com/a03-_inclusion.html
|
||||||
assert( is_vector(point,2) && is_path(poly,dim=2) && len(poly)>2,
|
assert( is_vector(point,2) && is_path(poly,dim=2) && len(poly)>2,
|
||||||
|
@ -1561,9 +1621,9 @@ function align_polygon(reference, poly, angles, cp) =
|
||||||
// Section: Convex Sets
|
// Section: Convex Sets
|
||||||
|
|
||||||
|
|
||||||
// Function: is_convex_polygon()
|
// Function: is_polygon_convex()
|
||||||
// Usage:
|
// Usage:
|
||||||
// test = is_convex_polygon(poly);
|
// test = is_polygon_convex(poly);
|
||||||
// Topics: Geometry, Convexity, Test
|
// Topics: Geometry, Convexity, Test
|
||||||
// Description:
|
// Description:
|
||||||
// Returns true if the given 2D or 3D polygon is convex.
|
// Returns true if the given 2D or 3D polygon is convex.
|
||||||
|
@ -1573,12 +1633,12 @@ function align_polygon(reference, poly, angles, cp) =
|
||||||
// poly = Polygon to check.
|
// poly = Polygon to check.
|
||||||
// eps = Tolerance for the collinearity test. Default: EPSILON.
|
// eps = Tolerance for the collinearity test. Default: EPSILON.
|
||||||
// Example:
|
// Example:
|
||||||
// test1 = is_convex_polygon(circle(d=50)); // Returns: true
|
// test1 = is_polygon_convex(circle(d=50)); // Returns: true
|
||||||
// test2 = is_convex_polygon(rot([50,120,30], p=path3d(circle(1,$fn=50)))); // Returns: true
|
// test2 = is_polygon_convex(rot([50,120,30], p=path3d(circle(1,$fn=50)))); // Returns: true
|
||||||
// Example:
|
// Example:
|
||||||
// spiral = [for (i=[0:36]) let(a=-i*10) (10+i)*[cos(a),sin(a)]];
|
// spiral = [for (i=[0:36]) let(a=-i*10) (10+i)*[cos(a),sin(a)]];
|
||||||
// test = is_convex_polygon(spiral); // Returns: false
|
// test = is_polygon_convex(spiral); // Returns: false
|
||||||
function is_convex_polygon(poly,eps=EPSILON) =
|
function is_polygon_convex(poly,eps=EPSILON) =
|
||||||
assert(is_path(poly), "The input should be a 2D or 3D polygon." )
|
assert(is_path(poly), "The input should be a 2D or 3D polygon." )
|
||||||
let(
|
let(
|
||||||
lp = len(poly),
|
lp = len(poly),
|
||||||
|
|
|
@ -42,7 +42,7 @@ test_circle_point_tangents();
|
||||||
|
|
||||||
test_noncollinear_triple();
|
test_noncollinear_triple();
|
||||||
test_polygon_area();
|
test_polygon_area();
|
||||||
test_is_convex_polygon();
|
test_is_polygon_convex();
|
||||||
test_polygon_shift();
|
test_polygon_shift();
|
||||||
test_polygon_shift_to_closest_point();
|
test_polygon_shift_to_closest_point();
|
||||||
test_reindex_polygon();
|
test_reindex_polygon();
|
||||||
|
@ -726,14 +726,14 @@ module test_polygon_area() {
|
||||||
*test_polygon_area();
|
*test_polygon_area();
|
||||||
|
|
||||||
|
|
||||||
module test_is_convex_polygon() {
|
module test_is_polygon_convex() {
|
||||||
assert(is_convex_polygon([[1,1],[-1,1],[-1,-1],[1,-1]]));
|
assert(is_polygon_convex([[1,1],[-1,1],[-1,-1],[1,-1]]));
|
||||||
assert(is_convex_polygon(circle(r=50,$fn=1000)));
|
assert(is_polygon_convex(circle(r=50,$fn=1000)));
|
||||||
assert(is_convex_polygon(rot([50,120,30], p=path3d(circle(1,$fn=50)))));
|
assert(is_polygon_convex(rot([50,120,30], p=path3d(circle(1,$fn=50)))));
|
||||||
assert(!is_convex_polygon([[1,1],[0,0],[-1,1],[-1,-1],[1,-1]]));
|
assert(!is_polygon_convex([[1,1],[0,0],[-1,1],[-1,-1],[1,-1]]));
|
||||||
assert(!is_convex_polygon([for (i=[0:36]) let(a=-i*10) (10+i)*[cos(a),sin(a)]])); // spiral
|
assert(!is_polygon_convex([for (i=[0:36]) let(a=-i*10) (10+i)*[cos(a),sin(a)]])); // spiral
|
||||||
}
|
}
|
||||||
*test_is_convex_polygon();
|
*test_is_polygon_convex();
|
||||||
|
|
||||||
|
|
||||||
module test_polygon_shift() {
|
module test_polygon_shift() {
|
||||||
|
|
Loading…
Reference in a new issue