2020-07-22 00:05:21 +00:00
|
|
|
include <../std.scad>
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2020-08-16 22:33:11 +00:00
|
|
|
//the commented lines are for tests to be written
|
|
|
|
//the tests are ordered as they appear in geometry.scad
|
|
|
|
|
2020-09-09 08:37:31 +00:00
|
|
|
|
|
|
|
|
2021-09-14 02:09:51 +00:00
|
|
|
test_point_on_line();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_collinear();
|
2021-06-21 19:19:07 +00:00
|
|
|
test_point_line_distance();
|
|
|
|
test_segment_distance();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_line_normal();
|
|
|
|
test_line_intersection();
|
2021-09-09 22:54:54 +00:00
|
|
|
//test_line_ray_intersection(); // should add this typ eof case
|
|
|
|
//test_ray_intersection(); // should add this type of case
|
|
|
|
//test_ray_segment_intersection(); // should add this type of case
|
2020-08-16 22:33:11 +00:00
|
|
|
test_line_closest_point();
|
2021-09-09 22:54:54 +00:00
|
|
|
//test_ray_closest_point(); // should add this type of case
|
2020-08-16 22:33:11 +00:00
|
|
|
test_line_from_points();
|
|
|
|
test_plane3pt();
|
|
|
|
test_plane3pt_indexed();
|
2020-09-09 08:37:31 +00:00
|
|
|
test_plane_from_normal();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_plane_from_points();
|
2020-09-09 08:37:31 +00:00
|
|
|
test_plane_from_polygon();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_plane_normal();
|
2020-09-09 08:37:31 +00:00
|
|
|
test_plane_offset();
|
2021-09-11 20:42:40 +00:00
|
|
|
test_plane_closest_point();
|
2021-06-21 19:19:07 +00:00
|
|
|
test_point_plane_distance();
|
2020-08-16 22:33:11 +00:00
|
|
|
|
2020-09-09 08:37:31 +00:00
|
|
|
test__general_plane_line_intersection();
|
|
|
|
test_plane_line_angle();
|
|
|
|
test_plane_line_intersection();
|
2020-08-29 02:07:10 +00:00
|
|
|
test_polygon_line_intersection();
|
2020-09-09 08:37:31 +00:00
|
|
|
test_plane_intersection();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_coplanar();
|
|
|
|
test_points_on_plane();
|
2021-09-10 22:16:42 +00:00
|
|
|
test_above_plane();
|
2020-09-25 07:01:45 +00:00
|
|
|
test_circle_2tangents();
|
|
|
|
test_circle_3points();
|
2020-09-09 08:37:31 +00:00
|
|
|
test_circle_point_tangents();
|
|
|
|
|
2020-08-16 22:33:11 +00:00
|
|
|
test_noncollinear_triple();
|
|
|
|
test_polygon_area();
|
2021-09-12 03:11:18 +00:00
|
|
|
test_is_polygon_convex();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_polygon_shift();
|
|
|
|
test_polygon_shift_to_closest_point();
|
|
|
|
test_reindex_polygon();
|
|
|
|
test_align_polygon();
|
|
|
|
test_centroid();
|
|
|
|
test_point_in_polygon();
|
2021-09-11 22:48:23 +00:00
|
|
|
test_is_polygon_clockwise();
|
2020-08-16 22:33:11 +00:00
|
|
|
test_clockwise_polygon();
|
|
|
|
test_ccw_polygon();
|
|
|
|
test_reverse_polygon();
|
2021-09-14 02:09:51 +00:00
|
|
|
|
|
|
|
test_polygon_normal();
|
2020-08-16 22:33:11 +00:00
|
|
|
|
|
|
|
//tests to migrate to other files
|
|
|
|
test_is_path();
|
|
|
|
test_is_closed_path();
|
|
|
|
test_close_path();
|
|
|
|
test_cleanup_path();
|
|
|
|
test_simplify_path();
|
|
|
|
test_simplify_path_indexed();
|
|
|
|
test_is_region();
|
2021-06-21 19:19:07 +00:00
|
|
|
test_convex_distance();
|
2021-06-21 19:43:12 +00:00
|
|
|
test_convex_collision();
|
2020-09-09 08:37:31 +00:00
|
|
|
|
2020-08-16 22:33:11 +00:00
|
|
|
// to be used when there are two alternative symmetrical outcomes
|
2020-09-09 08:37:31 +00:00
|
|
|
// from a function like a plane output; v must be a vector
|
2020-08-16 22:33:11 +00:00
|
|
|
function standardize(v) =
|
|
|
|
v==[]? [] :
|
2020-09-09 08:37:31 +00:00
|
|
|
let( i = max_index([for(vi=v) abs(vi) ]),
|
|
|
|
s = sign(v[i]) )
|
|
|
|
v*s;
|
|
|
|
|
|
|
|
|
|
|
|
module assert_std(vc,ve,info) { assert_approx(standardize(vc),standardize(ve),info); }
|
|
|
|
|
|
|
|
|
|
|
|
function info_str(list,i=0,string=chr(10)) =
|
|
|
|
assert(i>=len(list) || (is_list(list[i])&&len(list[i])>=2), "Invalid list for info_str." )
|
|
|
|
i>=len(list)
|
|
|
|
? str(string)
|
|
|
|
: info_str(list,i+1,str(string,str(list[i][0],_valstr(list[i][1]),chr(10))));
|
|
|
|
|
|
|
|
|
2021-09-11 23:35:05 +00:00
|
|
|
module test__normalize_plane(){
|
2020-12-22 23:15:25 +00:00
|
|
|
plane = rands(-5,5,4,seed=333)+[10,0,0,0];
|
2021-09-11 23:35:05 +00:00
|
|
|
plane2 = _normalize_plane(plane);
|
2020-09-09 08:37:31 +00:00
|
|
|
assert_approx(norm(point3d(plane2)),1);
|
|
|
|
assert_approx(plane*plane2[3],plane2*plane[3]);
|
|
|
|
}
|
2021-09-11 23:35:05 +00:00
|
|
|
test__normalize_plane();
|
2020-09-09 08:37:31 +00:00
|
|
|
|
|
|
|
module test_plane_line_intersection(){
|
2020-12-22 23:15:25 +00:00
|
|
|
line = [rands(-1,1,3,seed=74),rands(-1,1,3,seed=99)+[2,0,0]];
|
2020-09-09 08:37:31 +00:00
|
|
|
plane1 = plane_from_normal(line[1]-line[0],2*line[0]-line[1]); // plane disjoint from segment
|
|
|
|
plane2 = plane_from_normal(line[1]-line[0],(line[0]+line[1])/2); // through middle point of line
|
|
|
|
plane3 = plane3pt(line[1],line[0], rands(-1,1,3)+[0,3,0]); // containing line
|
|
|
|
plane4 = plane3pt(line[1],line[0], rands(-1,1,3)+[0,3,0])+[0,0,0,1]; // parallel to line
|
|
|
|
info1 = info_str([ ["line = ",line],["plane = ",plane1]]);
|
|
|
|
assert_approx(plane_line_intersection(plane1, line),2*line[0]-line[1],info1);
|
|
|
|
assert_approx(plane_line_intersection(plane1, line,[true,false]),undef,info1);
|
|
|
|
assert_approx(plane_line_intersection(plane1, line,[false,true]),2*line[0]-line[1],info1);
|
|
|
|
assert_approx(plane_line_intersection(plane1, line,[true, true]),undef,info1);
|
|
|
|
info2 = info_str([ ["line = ",line],["plane = ",plane2]]);
|
|
|
|
assert_approx(plane_line_intersection(plane2, line),(line[0]+line[1])/2,info2);
|
|
|
|
assert_approx(plane_line_intersection(plane2, line,[true,false]),(line[0]+line[1])/2,info2);
|
|
|
|
assert_approx(plane_line_intersection(plane2, line,[false,true]),(line[0]+line[1])/2,info2);
|
|
|
|
assert_approx(plane_line_intersection(plane2, line,[true, true]),(line[0]+line[1])/2,info2);
|
|
|
|
info3 = info_str([ ["line = ",line],["plane = ",plane3]]);
|
|
|
|
assert_approx(plane_line_intersection(plane3, line),line,info3);
|
|
|
|
assert_approx(plane_line_intersection(plane3, line,[true,false]),line,info3);
|
|
|
|
assert_approx(plane_line_intersection(plane3, line,[false,true]),line,info3);
|
|
|
|
assert_approx(plane_line_intersection(plane3, line,[true, true]),line,info3);
|
|
|
|
info4 = info_str([ ["line = ",line],["plane = ",plane4]]);
|
|
|
|
assert_approx(plane_line_intersection(plane4, line),undef,info4);
|
|
|
|
assert_approx(plane_line_intersection(plane4, line,[true,false]),undef,info4);
|
|
|
|
assert_approx(plane_line_intersection(plane4, line,[false,true]),undef,info4);
|
|
|
|
assert_approx(plane_line_intersection(plane4, line,[true, true]),undef,info4);
|
|
|
|
}
|
|
|
|
*test_plane_line_intersection();
|
|
|
|
|
|
|
|
|
|
|
|
module test_plane_intersection(){
|
|
|
|
line = [ rands(-1,1,3), rands(-1,1,3)+[2,0,0] ]; // a valid line
|
|
|
|
pt0 = line[0]-[2,0,0]; // 2 points not on the line
|
|
|
|
pt1 = line[1]-[0,2,0];
|
|
|
|
plane01 = plane3pt(line[0],line[1],pt0);
|
|
|
|
plane02 = plane3pt(line[0],line[1],pt1);
|
|
|
|
plane03 = plane3pt(line[0],pt0,pt1);
|
|
|
|
info = info_str([["plane1 = ",plane01],["plane2 = ",plane02],["plane3 = ",plane03]]);
|
|
|
|
assert_approx(plane_intersection(plane01,plane02,plane03),line[0],info);
|
|
|
|
assert_approx(plane_intersection(plane01,2*plane01),undef,info);
|
|
|
|
lineInters = plane_intersection(plane01,plane02);
|
|
|
|
assert_approx(line_closest_point(lineInters,line[0]), line[0], info);
|
|
|
|
assert_approx(line_closest_point(lineInters,line[1]), line[1], info);
|
|
|
|
}
|
|
|
|
*test_plane_intersection();
|
|
|
|
|
|
|
|
|
|
|
|
module test_plane_offset(){
|
|
|
|
plane = rands(-1,1,4)+[2,0,0,0]; // a valid plane
|
|
|
|
info = info_str([["plane = ",plane]]);
|
2021-09-11 23:35:05 +00:00
|
|
|
assert_approx(plane_offset(plane), _normalize_plane(plane)[3],info);
|
2020-09-09 08:37:31 +00:00
|
|
|
assert_approx(plane_offset([1,1,1,1]), 1/sqrt(3),info);
|
|
|
|
}
|
|
|
|
*test_plane_offset();
|
|
|
|
|
|
|
|
module test_plane_from_polygon(){
|
|
|
|
poly1 = [ rands(-1,1,3), rands(-1,1,3)+[2,0,0], rands(-1,1,3)+[0,2,2] ];
|
|
|
|
poly2 = concat(poly1, [sum(poly1)/3] );
|
|
|
|
info = info_str([["poly1 = ",poly1],["poly2 = ",poly2]]);
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_approx(plane_from_polygon(poly1),plane3pt(poly1[0],poly1[1],poly1[2]),info);
|
|
|
|
assert_approx(plane_from_polygon(poly2),plane3pt(poly1[0],poly1[1],poly1[2]),info);
|
2020-09-09 08:37:31 +00:00
|
|
|
}
|
|
|
|
*test_plane_from_polygon();
|
|
|
|
|
|
|
|
module test_plane_from_normal(){
|
|
|
|
normal = rands(-1,1,3)+[2,0,0];
|
|
|
|
point = rands(-1,1,3);
|
|
|
|
displ = normal*point;
|
|
|
|
info = info_str([["normal = ",normal],["point = ",point],["displ = ",displ]]);
|
|
|
|
assert_approx(plane_from_normal(normal,point)*[each point,-1],0,info);
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_approx(plane_from_normal([1,1,1],[1,2,3]),[0.57735026919,0.57735026919,0.57735026919,3.46410161514]);
|
2020-09-09 08:37:31 +00:00
|
|
|
}
|
|
|
|
*test_plane_from_normal();
|
|
|
|
|
|
|
|
module test_plane_line_angle() {
|
|
|
|
angs = rands(0,360,3);
|
|
|
|
displ = rands(-1,1,1)[0];
|
|
|
|
info = info_str([["angs = ",angs],["displ = ",displ]]);
|
|
|
|
assert_approx(plane_line_angle([each rot(angs,p=[0,0,1]),displ],[[0,0,0],rot(angs,p=[0,0,1])]),90,info);
|
|
|
|
assert_approx(plane_line_angle([each rot(angs,p=[0,0,1]),displ],[[0,0,0],rot(angs,p=[0,1,1])]),45,info);
|
|
|
|
assert_approx(plane_line_angle([each rot(angs,p=[0,0,1]),0],[[0,0,0],rot(angs,p=[1,1,1])]),35.2643896828);
|
|
|
|
}
|
|
|
|
*test_plane_line_angle();
|
|
|
|
|
|
|
|
module test__general_plane_line_intersection() {
|
|
|
|
CRLF = chr(10);
|
|
|
|
// general line
|
|
|
|
plane1 = rands(-1,1,4)+[2,0,0,0]; // a random valid plane (normal!=0)
|
|
|
|
line1 = [ rands(-1,1,3), rands(-1,1,3)+[2,0,0] ]; // a random valid line (line1[0]!=line1[1])
|
|
|
|
inters1 = _general_plane_line_intersection(plane1, line1);
|
|
|
|
info1 = info_str([["line = ",line1],["plane = ",plane1]]);
|
|
|
|
if(inters1==undef) { // parallel to the plane ?
|
|
|
|
assert_approx( point3d(plane1)*(line1[1]-line1[0]), 0, info1);
|
|
|
|
assert( point3d(plane1)*line1[0]== plane1[3], info1); // not on the plane
|
|
|
|
}
|
|
|
|
if( inters1[1]==undef) { // on the plane ?
|
|
|
|
assert_approx( point3d(plane1)*(line1[1]-line1[0]), 0, info1);
|
|
|
|
assert_approx(point3d(plane1)*line1[0],plane1[3], info1) ; // on the plane
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
interspoint = line1[0]+inters1[1]*(line1[1]-line1[0]);
|
|
|
|
assert_approx(inters1[0],interspoint, info1);
|
|
|
|
assert_approx(point3d(plane1)*inters1[0], plane1[3], info1); // interspoint on the plane
|
2021-06-21 19:19:07 +00:00
|
|
|
assert_approx(point_plane_distance(plane1, inters1[0]), 0, info1); // inters1[0] on the plane
|
2020-09-09 08:37:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// line parallel to the plane
|
|
|
|
line2 = [ rands(-1,1,3)+[0,2,0], rands(-1,1,3)+[2,0,0] ]; // a random valid line2
|
|
|
|
// not containing the origin
|
|
|
|
plane0 = plane_from_points([line2[0], line2[1], [0,0,0]]); // plane cointaining the line
|
|
|
|
plane2 = plane_from_normal(plane_normal(plane0), [5,5,5]);
|
|
|
|
inters2 = _general_plane_line_intersection(plane2, line2);
|
|
|
|
info2 = info_str([["line = ",line2],["plane = ",plane2]]);
|
|
|
|
assert(inters2==undef, info2);
|
|
|
|
|
|
|
|
// line on the plane
|
|
|
|
line3 = [ rands(-1,1,3), rands(-1,1,3)+[2,0,0] ]; // a random valid line
|
|
|
|
imax = max_index(line3[1]-line3[0]);
|
|
|
|
w = [for(j=[0:2]) imax==j? 0: 3 ];
|
|
|
|
p3 = line3[0] + cross(line3[1]-line3[0],w); // a point not on the line
|
|
|
|
plane3 = plane_from_points([line3[0], line3[1], p3]); // plane containing line
|
|
|
|
inters3 = _general_plane_line_intersection(plane3, line3);
|
|
|
|
info3 = info_str([["line = ",line3],["plane = ",plane3]]);
|
|
|
|
assert(!is_undef(inters3) && inters3[1]==undef, info3);
|
|
|
|
assert_approx(inters3[0], line3, info3);
|
|
|
|
}
|
|
|
|
*test__general_plane_line_intersection();
|
2020-08-16 22:33:11 +00:00
|
|
|
|
2020-08-20 21:42:24 +00:00
|
|
|
|
2020-08-16 22:33:11 +00:00
|
|
|
module test_points_on_plane() {
|
|
|
|
pts = [for(i=[0:40]) rands(-1,1,3) ];
|
|
|
|
dir = rands(-10,10,3);
|
2020-09-09 08:37:31 +00:00
|
|
|
normal0 = [1,2,3];
|
2020-08-16 22:33:11 +00:00
|
|
|
ang = rands(0,360,1)[0];
|
|
|
|
normal = rot(a=ang,p=normal0);
|
|
|
|
plane = [each normal, normal*dir];
|
2021-09-11 20:42:40 +00:00
|
|
|
prj_pts = plane_closest_point(plane,pts);
|
2020-09-09 08:37:31 +00:00
|
|
|
info = info_str([["pts = ",pts],["dir = ",dir],["ang = ",ang]]);
|
|
|
|
assert(points_on_plane(prj_pts,plane),info);
|
|
|
|
assert(!points_on_plane(concat(pts,[normal-dir]),plane),info);
|
2020-08-16 22:33:11 +00:00
|
|
|
}
|
|
|
|
*test_points_on_plane();
|
|
|
|
|
2021-09-11 20:42:40 +00:00
|
|
|
module test_plane_closest_point(){
|
2020-08-16 22:33:11 +00:00
|
|
|
ang = rands(0,360,1)[0];
|
|
|
|
dir = rands(-10,10,3);
|
|
|
|
normal0 = unit([1,2,3]);
|
|
|
|
normal = rot(a=ang,p=normal0);
|
|
|
|
plane0 = [each normal0, 0];
|
|
|
|
plane = [each normal, 0];
|
|
|
|
planem = [each normal, normal*dir];
|
|
|
|
pts = [for(i=[1:10]) rands(-1,1,3)];
|
2020-09-09 08:37:31 +00:00
|
|
|
info = info_str([["ang = ",ang],["dir = ",dir]]);
|
2021-09-11 20:42:40 +00:00
|
|
|
assert_approx( plane_closest_point(plane,pts),
|
|
|
|
plane_closest_point(plane,plane_closest_point(plane,pts)),info);
|
|
|
|
assert_approx( plane_closest_point(plane,pts),
|
|
|
|
rot(a=ang,p=plane_closest_point(plane0,rot(a=-ang,p=pts))),info);
|
|
|
|
assert_approx( move((-normal*dir)*normal,p=plane_closest_point(planem,pts)),
|
|
|
|
plane_closest_point(plane,pts),info);
|
|
|
|
assert_approx( move((normal*dir)*normal,p=plane_closest_point(plane,pts)),
|
|
|
|
plane_closest_point(planem,pts),info);
|
2020-08-16 22:33:11 +00:00
|
|
|
}
|
2021-09-11 20:42:40 +00:00
|
|
|
*test_plane_closest_point();
|
2020-08-16 22:33:11 +00:00
|
|
|
|
|
|
|
module test_line_from_points() {
|
|
|
|
assert_approx(line_from_points([[1,0],[0,0],[-1,0]]),[[-1,0],[1,0]]);
|
|
|
|
assert_approx(line_from_points([[1,1],[0,1],[-1,1]]),[[-1,1],[1,1]]);
|
|
|
|
assert(line_from_points([[1,1],[0,1],[-1,0]])==undef);
|
|
|
|
assert(line_from_points([[1,1],[0,1],[-1,0]],fast=true)== [[-1,0],[1,1]]);
|
|
|
|
}
|
|
|
|
*test_line_from_points();
|
|
|
|
|
2021-09-14 02:09:51 +00:00
|
|
|
module test_point_on_line() {
|
|
|
|
assert(point_on_line([-15,0], [[-10,0], [10,0]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([-10,0], [[-10,0], [10,0]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([-5,0], [[-10,0], [10,0]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([0,0], [[-10,0], [10,0]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([3,3], [[-10,0], [10,0]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([5,0], [[-10,0], [10,0]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([10,0], [[-10,0], [10,0]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([15,0], [[-10,0], [10,0]],SEGMENT) == false);
|
|
|
|
|
|
|
|
assert(point_on_line([0,-15], [[0,-10], [0,10]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([0,-10], [[0,-10], [0,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([0, -5], [[0,-10], [0,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([0, 0], [[0,-10], [0,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([3, 3], [[0,-10], [0,10]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([0, 5], [[0,-10], [0,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([0, 10], [[0,-10], [0,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([0, 15], [[0,-10], [0,10]],SEGMENT) == false);
|
|
|
|
|
|
|
|
assert(point_on_line([-15,-15], [[-10,-10], [10,10]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([-10,-10], [[-10,-10], [10,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([ -5, -5], [[-10,-10], [10,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([ 0, 0], [[-10,-10], [10,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([ 0, 3], [[-10,-10], [10,10]],SEGMENT) == false);
|
|
|
|
assert(point_on_line([ 5, 5], [[-10,-10], [10,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([ 10, 10], [[-10,-10], [10,10]],SEGMENT) == true);
|
|
|
|
assert(point_on_line([ 15, 15], [[-10,-10], [10,10]],SEGMENT) == false);
|
|
|
|
|
|
|
|
assert(point_on_line([10,10], [[0,0],[5,5]]) == true);
|
|
|
|
assert(point_on_line([4,4], [[0,0],[5,5]]) == true);
|
|
|
|
assert(point_on_line([-2,-2], [[0,0],[5,5]]) == true);
|
|
|
|
assert(point_on_line([5,5], [[0,0],[5,5]]) == true);
|
|
|
|
assert(point_on_line([10,10], [[0,0],[5,5]],RAY) == true);
|
|
|
|
assert(point_on_line([0,0], [[0,0],[5,5]],RAY) == true);
|
|
|
|
assert(point_on_line([3,3], [[0,0],[5,5]],RAY) == true);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2021-09-14 02:09:51 +00:00
|
|
|
*test_point_on_line();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2021-09-11 23:35:05 +00:00
|
|
|
module test__point_left_of_line2d() {
|
|
|
|
assert(_point_left_of_line2d([ -3, 0], [[-10,-10], [10,10]]) > 0);
|
|
|
|
assert(_point_left_of_line2d([ 0, 0], [[-10,-10], [10,10]]) == 0);
|
|
|
|
assert(_point_left_of_line2d([ 3, 0], [[-10,-10], [10,10]]) < 0);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2021-09-11 23:35:05 +00:00
|
|
|
test__point_left_of_line2d();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
module test_collinear() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(collinear([-10,-10], [-15, -16], [10,10]) == false);
|
2020-08-16 22:33:11 +00:00
|
|
|
assert(collinear([[-10,-10], [-15, -16], [10,10]]) == false);
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(collinear([-10,-10], [-15, -15], [10,10]) == true);
|
2020-08-16 22:33:11 +00:00
|
|
|
assert(collinear([[-10,-10], [-15, -15], [10,10]]) == true);
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(collinear([-10,-10], [ -3, 0], [10,10]) == false);
|
|
|
|
assert(collinear([-10,-10], [ 0, 0], [10,10]) == true);
|
|
|
|
assert(collinear([-10,-10], [ 3, 0], [10,10]) == false);
|
|
|
|
assert(collinear([-10,-10], [ 15, 15], [10,10]) == true);
|
|
|
|
assert(collinear([-10,-10], [ 15, 16], [10,10]) == false);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_collinear();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2021-06-21 19:19:07 +00:00
|
|
|
module test_point_line_distance() {
|
|
|
|
assert_approx(point_line_distance([1,1,1], [[-10,-10,-10], [10,10,10]]), 0);
|
|
|
|
assert_approx(point_line_distance([-1,-1,-1], [[-10,-10,-10], [10,10,10]]), 0);
|
|
|
|
assert_approx(point_line_distance([1,-1,0], [[-10,-10,-10], [10,10,10]]), sqrt(2));
|
|
|
|
assert_approx(point_line_distance([8,-8,0], [[-10,-10,-10], [10,10,10]]), 8*sqrt(2));
|
2021-09-09 22:54:54 +00:00
|
|
|
assert_approx(point_line_distance([3,8], [[-10,0], [10,0]],SEGMENT), 8);
|
|
|
|
assert_approx(point_line_distance([14,3], [[-10,0], [10,0]],SEGMENT), 5);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2021-06-21 19:19:07 +00:00
|
|
|
*test_point_line_distance();
|
|
|
|
|
|
|
|
|
|
|
|
module test_segment_distance() {
|
|
|
|
assert_approx(segment_distance([[-14,3], [-14,9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[-14,3], [-15,9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[14,3], [14,9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[-14,-3], [-14,-9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[-14,-3], [-15,-9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[14,-3], [14,-9]], [[-10,0], [10,0]]), 5);
|
|
|
|
assert_approx(segment_distance([[14,3], [14,-3]], [[-10,0], [10,0]]), 4);
|
|
|
|
assert_approx(segment_distance([[-14,3], [-14,-3]], [[-10,0], [10,0]]), 4);
|
|
|
|
assert_approx(segment_distance([[-6,5], [4,-5]], [[-10,0], [10,0]]), 0);
|
|
|
|
assert_approx(segment_distance([[-5,5], [5,-5]], [[-10,3], [10,-3]]), 0);
|
|
|
|
}
|
|
|
|
*test_segment_distance();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2019-10-25 22:17:55 +00:00
|
|
|
module test_line_normal() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(line_normal([0,0],[10,0]) == [0,1]);
|
|
|
|
assert(line_normal([0,0],[0,10]) == [-1,0]);
|
|
|
|
assert(line_normal([0,0],[-10,0]) == [0,-1]);
|
|
|
|
assert(line_normal([0,0],[0,-10]) == [1,0]);
|
|
|
|
assert(approx(line_normal([0,0],[10,10]), [-sqrt(2)/2,sqrt(2)/2]));
|
|
|
|
assert(line_normal([[0,0],[10,0]]) == [0,1]);
|
|
|
|
assert(line_normal([[0,0],[0,10]]) == [-1,0]);
|
|
|
|
assert(line_normal([[0,0],[-10,0]]) == [0,-1]);
|
|
|
|
assert(line_normal([[0,0],[0,-10]]) == [1,0]);
|
|
|
|
assert(approx(line_normal([[0,0],[10,10]]), [-sqrt(2)/2,sqrt(2)/2]));
|
2020-07-10 07:03:55 +00:00
|
|
|
pts = [for (p=pair(rands(-100,100,1000,seed_value=4312))) p];
|
2021-01-25 07:26:39 +00:00
|
|
|
for (p = pair(pts,true)) {
|
2020-05-30 02:04:34 +00:00
|
|
|
p1 = p.x;
|
|
|
|
p2 = p.y;
|
|
|
|
n = unit(p2-p1);
|
|
|
|
n1 = [-n.y, n.x];
|
|
|
|
n2 = line_normal(p1,p2);
|
|
|
|
assert(approx(n2, n1));
|
|
|
|
}
|
2019-10-25 22:17:55 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_line_normal();
|
2019-10-25 22:17:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_line_intersection() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(line_intersection([[-10,-10], [ -1,-10]], [[ 10,-10], [ 1,-10]]) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ -1, 0]], [[ 10, 0], [ 1, 0]]) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ -1, 0]], [[ 1, 0], [ 10, 0]]) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ 10, 0]], [[-10, 0], [ 10, 0]]) == undef);
|
|
|
|
assert(line_intersection([[-10, 10], [ 10, 10]], [[-10,-10], [ 10,-10]]) == undef);
|
|
|
|
assert(line_intersection([[-10,-10], [ -1, -1]], [[ 10,-10], [ 1, -1]]) == [0,0]);
|
|
|
|
assert(line_intersection([[-10,-10], [ 10, 10]], [[ 10,-10], [-10, 10]]) == [0,0]);
|
|
|
|
assert(line_intersection([[ -8, 0], [ 12, 4]], [[ 12, 0], [ -8, 4]]) == [2,2]);
|
2021-09-09 22:54:54 +00:00
|
|
|
assert(line_intersection([[-10,-10], [ -1,-10]], [[ 10,-10], [ 1,-10]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ -1, 0]], [[ 10, 0], [ 1, 0]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ -1, 0]], [[ 1, 0], [ 10, 0]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10, 0], [ 10, 0]], [[-10, 0], [ 10, 0]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10, 10], [ 10, 10]], [[-10,-10], [ 10,-10]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10,-10], [ -1, -1]], [[ 10,-10], [ 1, -1]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10,-10], [ 10, 10]], [[ 10,-10], [-10, 10]],LINE,SEGMENT) == [0,0]);
|
|
|
|
assert(line_intersection([[ -8, 0], [ 12, 4]], [[ 12, 0], [ -8, 4]],LINE,SEGMENT) == [2,2]);
|
|
|
|
assert(line_intersection([[-10,-10], [ 10, 10]], [[ 10,-10], [ 1, -1]],LINE,SEGMENT) == undef);
|
|
|
|
assert(line_intersection([[-10,-10], [ 10, 10]], [[ 10,-10], [ -1, 1]],LINE,SEGMENT) == [0,0]);
|
2019-10-25 22:17:55 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_line_intersection();
|
2019-10-25 22:17:55 +00:00
|
|
|
|
|
|
|
|
2019-10-30 05:47:38 +00:00
|
|
|
module test_line_closest_point() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(approx(line_closest_point([[-10,-10], [10,10]], [1,-1]), [0,0]));
|
|
|
|
assert(approx(line_closest_point([[-10,-10], [10,10]], [-1,1]), [0,0]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [1,2]+[-2,1]), [1,2]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [1,2]+[2,-1]), [1,2]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [13,31]), [15,30]));
|
2021-09-09 22:54:54 +00:00
|
|
|
assert(approx(line_closest_point([[-10,-10], [10,10]], [1,-1],SEGMENT), [0,0]));
|
|
|
|
assert(approx(line_closest_point([[-10,-10], [10,10]], [-1,1],SEGMENT), [0,0]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [1,2]+[-2,1],SEGMENT), [1,2]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [1,2]+[2,-1],SEGMENT), [1,2]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [13,31],SEGMENT), [10,20]));
|
|
|
|
assert(approx(line_closest_point([[-10,-20], [10,20]], [15,25],SEGMENT), [10,20]));
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_line_closest_point();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
2020-09-25 07:01:45 +00:00
|
|
|
module test_circle_2tangents() {
|
2020-08-16 22:33:11 +00:00
|
|
|
//** missing tests with arg tangent=true
|
2020-09-25 07:01:45 +00:00
|
|
|
assert(approx(circle_2tangents([10,10],[0,0],[10,-10],r=10/sqrt(2))[0],[10,0]));
|
|
|
|
assert(approx(circle_2tangents([-10,10],[0,0],[-10,-10],r=10/sqrt(2))[0],[-10,0]));
|
|
|
|
assert(approx(circle_2tangents([-10,10],[0,0],[10,10],r=10/sqrt(2))[0],[0,10]));
|
|
|
|
assert(approx(circle_2tangents([-10,-10],[0,0],[10,-10],r=10/sqrt(2))[0],[0,-10]));
|
|
|
|
assert(approx(circle_2tangents([0,10],[0,0],[10,0],r=10)[0],[10,10]));
|
|
|
|
assert(approx(circle_2tangents([10,0],[0,0],[0,-10],r=10)[0],[10,-10]));
|
|
|
|
assert(approx(circle_2tangents([0,-10],[0,0],[-10,0],r=10)[0],[-10,-10]));
|
|
|
|
assert(approx(circle_2tangents([-10,0],[0,0],[0,10],r=10)[0],[-10,10]));
|
|
|
|
assert_approx(circle_2tangents(polar_to_xy(10,60),[0,0],[10,0],r=10)[0],polar_to_xy(20,30));
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-09-25 07:01:45 +00:00
|
|
|
*test_circle_2tangents();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
2020-09-25 07:01:45 +00:00
|
|
|
module test_circle_3points() {
|
2020-05-30 02:04:34 +00:00
|
|
|
count = 200;
|
|
|
|
coords = rands(-100,100,count,seed_value=888);
|
|
|
|
radii = rands(10,100,count,seed_value=390);
|
|
|
|
angles = rands(0,360,count,seed_value=699);
|
|
|
|
// 2D tests.
|
2021-04-08 03:57:45 +00:00
|
|
|
for(i = count(count)) {
|
2020-05-30 02:04:34 +00:00
|
|
|
cp = select(coords,i,i+1);
|
|
|
|
r = radii[i];
|
|
|
|
angs = sort(select(angles,i,i+2));
|
|
|
|
pts = [for (a=angs) cp+polar_to_xy(r,a)];
|
2020-09-25 07:01:45 +00:00
|
|
|
res = circle_3points(pts);
|
2020-05-30 02:04:34 +00:00
|
|
|
if (!approx(res[0], cp)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[0], expected=cp, delta=res[0]-cp);
|
|
|
|
assert(approx(res[0], cp));
|
|
|
|
}
|
|
|
|
if (!approx(res[1], r)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[1], expected=r, delta=res[1]-r);
|
|
|
|
assert(approx(res[1], r));
|
|
|
|
}
|
|
|
|
if (!approx(res[2], UP)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[2], expected=UP, delta=res[2]-UP);
|
|
|
|
assert(approx(res[2], UP));
|
|
|
|
}
|
|
|
|
}
|
2021-04-08 03:57:45 +00:00
|
|
|
for(i = count(count)) {
|
2020-05-30 02:04:34 +00:00
|
|
|
cp = select(coords,i,i+1);
|
|
|
|
r = radii[i];
|
|
|
|
angs = sort(select(angles,i,i+2));
|
|
|
|
pts = [for (a=angs) cp+polar_to_xy(r,a)];
|
2020-09-25 07:01:45 +00:00
|
|
|
res = circle_3points(pts[0], pts[1], pts[2]);
|
2020-05-30 02:04:34 +00:00
|
|
|
if (!approx(res[0], cp)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[0], expected=cp, delta=res[0]-cp);
|
|
|
|
assert(approx(res[0], cp));
|
|
|
|
}
|
|
|
|
if (!approx(res[1], r)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[1], expected=r, delta=res[1]-r);
|
|
|
|
assert(approx(res[1], r));
|
|
|
|
}
|
|
|
|
if (!approx(res[2], UP)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo(got=res[2], expected=UP, delta=res[2]-UP);
|
|
|
|
assert(approx(res[2], UP));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 3D tests.
|
2021-04-08 03:57:45 +00:00
|
|
|
for(i = count(count)) {
|
2020-05-30 02:04:34 +00:00
|
|
|
cp = select(coords,i,i+2);
|
|
|
|
r = radii[i];
|
|
|
|
nrm = unit(select(coords,i+10,i+12));
|
|
|
|
n = nrm.z<0? -nrm : nrm;
|
|
|
|
angs = sort(select(angles,i,i+2));
|
|
|
|
pts = translate(cp,p=rot(from=UP,to=n,p=[for (a=angs) point3d(polar_to_xy(r,a))]));
|
2020-09-25 07:01:45 +00:00
|
|
|
res = circle_3points(pts);
|
2020-05-30 02:04:34 +00:00
|
|
|
if (!approx(res[0], cp)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("CP:", got=res[0], expected=cp, delta=res[0]-cp);
|
|
|
|
assert(approx(res[0], cp));
|
|
|
|
}
|
|
|
|
if (!approx(res[1], r)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("R:", got=res[1], expected=r, delta=res[1]-r);
|
|
|
|
assert(approx(res[1], r));
|
|
|
|
}
|
|
|
|
if (!approx(res[2], n)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("NORMAL:", got=res[2], expected=n, delta=res[2]-n);
|
|
|
|
assert(approx(res[2], n));
|
|
|
|
}
|
|
|
|
}
|
2021-04-08 03:57:45 +00:00
|
|
|
for(i = count(count)) {
|
2020-05-30 02:04:34 +00:00
|
|
|
cp = select(coords,i,i+2);
|
|
|
|
r = radii[i];
|
|
|
|
nrm = unit(select(coords,i+10,i+12));
|
|
|
|
n = nrm.z<0? -nrm : nrm;
|
|
|
|
angs = sort(select(angles,i,i+2));
|
|
|
|
pts = translate(cp,p=rot(from=UP,to=n,p=[for (a=angs) point3d(polar_to_xy(r,a))]));
|
2020-09-25 07:01:45 +00:00
|
|
|
res = circle_3points(pts[0], pts[1], pts[2]);
|
2020-05-30 02:04:34 +00:00
|
|
|
if (!approx(res[0], cp)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("CENTER:", got=res[0], expected=cp, delta=res[0]-cp);
|
|
|
|
assert(approx(res[0], cp));
|
|
|
|
}
|
|
|
|
if (!approx(res[1], r)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("RADIUS:", got=res[1], expected=r, delta=res[1]-r);
|
|
|
|
assert(approx(res[1], r));
|
|
|
|
}
|
|
|
|
if (!approx(res[2], n)) {
|
|
|
|
echo(cp=cp, r=r, angs=angs, n=n);
|
|
|
|
echo(pts=pts);
|
|
|
|
echo("NORMAL:", got=res[2], expected=n, delta=res[2]-n);
|
|
|
|
assert(approx(res[2], n));
|
|
|
|
}
|
|
|
|
}
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-09-25 07:01:45 +00:00
|
|
|
*test_circle_3points();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
2020-05-24 02:22:44 +00:00
|
|
|
module test_circle_point_tangents() {
|
2020-09-25 00:09:06 +00:00
|
|
|
testvals = [
|
|
|
|
// cp r pt expect
|
|
|
|
[[0,0], 50, [50*sqrt(2),0], [polar_to_xy(50,45), polar_to_xy(50,-45)]],
|
|
|
|
[[5,10], 50, [5+50*sqrt(2),10], [[5,10]+polar_to_xy(50,45), [5,10]+polar_to_xy(50,-45)]],
|
|
|
|
[[0,0], 50, [0,50*sqrt(2)], [polar_to_xy(50,135), polar_to_xy(50,45)]],
|
2021-02-02 18:18:43 +00:00
|
|
|
[[5,10], 50, [5,10+50*sqrt(2)], [[5,10]+polar_to_xy(50,135), [5,10]+polar_to_xy(50,45)]],
|
|
|
|
[[5,10], 50, [5,10+50*sqrt(2)], [[5,10]+polar_to_xy(50,135), [5,10]+polar_to_xy(50,45)]],
|
|
|
|
[[5,10], 50, [5, 60], [[5, 60]]],
|
|
|
|
[[5,10], 50, [5, 59], []],
|
2020-09-25 00:09:06 +00:00
|
|
|
];
|
|
|
|
for (v = testvals) {
|
|
|
|
cp = v[0]; r = v[1]; pt = v[2]; expect = v[3];
|
|
|
|
info = str("cp=",cp, ", r=",r, ", pt=",pt);
|
|
|
|
assert_approx(circle_point_tangents(r=r,cp=cp,pt=pt), expect, info);
|
2020-05-30 02:04:34 +00:00
|
|
|
}
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_circle_point_tangents();
|
2019-10-25 22:17:55 +00:00
|
|
|
|
|
|
|
|
2019-05-02 02:28:02 +00:00
|
|
|
module test_plane3pt() {
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_approx(plane3pt([0,0,20], [0,10,10], [0,0,0]), [1,0,0,0]);
|
|
|
|
assert_approx(plane3pt([2,0,20], [2,10,10], [2,0,0]), [1,0,0,2]);
|
|
|
|
assert_approx(plane3pt([0,0,0], [10,0,10], [0,0,20]), [0,1,0,0]);
|
|
|
|
assert_approx(plane3pt([0,2,0], [10,2,10], [0,2,20]), [0,1,0,2]);
|
|
|
|
assert_approx(plane3pt([0,0,0], [10,10,0], [20,0,0]), [0,0,1,0]);
|
|
|
|
assert_approx(plane3pt([0,0,2], [10,10,2], [20,0,2]), [0,0,1,2]);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_plane3pt();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
module test_plane3pt_indexed() {
|
2020-05-30 02:04:34 +00:00
|
|
|
pts = [ [0,0,0], [10,0,0], [0,10,0], [0,0,10] ];
|
|
|
|
s13 = sqrt(1/3);
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_approx(plane3pt_indexed(pts, 0,3,2), [1,0,0,0]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 0,2,3), [-1,0,0,0]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 0,1,3), [0,1,0,0]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 0,3,1), [0,-1,0,0]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 0,2,1), [0,0,1,0]);
|
2020-08-16 22:33:11 +00:00
|
|
|
assert_approx(plane3pt_indexed(pts, 0,1,2), [0,0,-1,0]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 3,2,1), [s13,s13,s13,10*s13]);
|
|
|
|
assert_approx(plane3pt_indexed(pts, 1,2,3), [-s13,-s13,-s13,-10*s13]);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_plane3pt_indexed();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
2020-03-20 20:53:47 +00:00
|
|
|
module test_plane_from_points() {
|
2020-08-20 21:42:24 +00:00
|
|
|
assert_std(plane_from_points([[0,0,20], [0,10,10], [0,0,0], [0,5,3]]), [1,0,0,0]);
|
2021-04-10 19:14:40 +00:00
|
|
|
assert_std(plane_from_points([[2,0,20], [2,10,10], [2,0,0], [2,3,4]]), [1,0,0,2]);
|
2020-08-20 21:42:24 +00:00
|
|
|
assert_std(plane_from_points([[0,0,0], [10,0,10], [0,0,20], [5,0,7]]), [0,1,0,0]);
|
|
|
|
assert_std(plane_from_points([[0,2,0], [10,2,10], [0,2,20], [4,2,3]]), [0,1,0,2]);
|
|
|
|
assert_std(plane_from_points([[0,0,0], [10,10,0], [20,0,0], [8,3,0]]), [0,0,1,0]);
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_std(plane_from_points([[0,0,2], [10,10,2], [20,0,2], [3,4,2]]), [0,0,1,2]);
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_plane_from_points();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
2021-09-14 02:09:51 +00:00
|
|
|
module test_polygon_normal() {
|
|
|
|
circ = path3d(circle($fn=37, r=3));
|
|
|
|
|
|
|
|
assert_approx(polygon_normal(circ), UP);
|
|
|
|
assert_approx(polygon_normal(rot(from=UP,to=[1,2,3],p=circ)), unit([1,2,3]));
|
|
|
|
assert_approx(polygon_normal(rot(from=UP,to=[4,-2,3],p=reverse(circ))), -unit([4,-2,3]));
|
|
|
|
assert_approx(polygon_normal(path3d([[0,0], [10,10], [11,10], [0,-1], [-1,1]])), UP);
|
|
|
|
}
|
|
|
|
*test_polygon_normal();
|
|
|
|
|
2019-10-30 05:47:38 +00:00
|
|
|
module test_plane_normal() {
|
2021-04-10 20:07:23 +00:00
|
|
|
assert_approx(plane_normal(plane3pt([0,0,20], [0,10,10], [0,0,0])), [1,0,0]);
|
|
|
|
assert_approx(plane_normal(plane3pt([2,0,20], [2,10,10], [2,0,0])), [1,0,0]);
|
|
|
|
assert_approx(plane_normal(plane3pt([0,0,0], [10,0,10], [0,0,20])), [0,1,0]);
|
|
|
|
assert_approx(plane_normal(plane3pt([0,2,0], [10,2,10], [0,2,20])), [0,1,0]);
|
|
|
|
assert_approx(plane_normal(plane3pt([0,0,0], [10,10,0], [20,0,0])), [0,0,1]);
|
|
|
|
assert_approx(plane_normal(plane3pt([0,0,2], [10,10,2], [20,0,2])), [0,0,1]);
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_plane_normal();
|
2019-10-25 22:17:55 +00:00
|
|
|
|
|
|
|
|
2021-06-21 19:19:07 +00:00
|
|
|
module test_point_plane_distance() {
|
2020-05-30 02:04:34 +00:00
|
|
|
plane1 = plane3pt([-10,0,0], [0,10,0], [10,0,0]);
|
2021-06-21 19:19:07 +00:00
|
|
|
assert(point_plane_distance(plane1, [0,0,5]) == 5);
|
|
|
|
assert(point_plane_distance(plane1, [5,5,8]) == 8);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2021-06-21 19:19:07 +00:00
|
|
|
*test_point_plane_distance();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2020-08-29 02:07:10 +00:00
|
|
|
module test_polygon_line_intersection() {
|
2020-09-09 08:37:31 +00:00
|
|
|
poly0 = [ [-10,-10, 0],[10,-10, 0],[10,10,0],[0,5,0],[-10,10,0] ];
|
|
|
|
line0 = [ [-3,7.5,0],[3,7.5,0] ]; // a segment on poly0 plane, out of poly0
|
|
|
|
angs = rands(0,360,3);
|
|
|
|
poly = rot(angs,p=poly0);
|
|
|
|
lineon = rot(angs,p=line0);
|
|
|
|
info = info_str([["angs = ",angs],["line = ",lineon],["poly = ",poly]]);
|
|
|
|
// line on polygon plane
|
|
|
|
assert_approx(polygon_line_intersection(poly,lineon,bounded=[true,true]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,lineon,bounded=[true,false]),
|
|
|
|
[rot(angs,p=[[5,7.5,0],[10,7.5,0]])], info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,lineon,bounded=[false,true]),
|
|
|
|
[rot(angs,p=[[-10,7.5,0],[-5,7.5,0]])], info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,lineon,bounded=[false,false]),
|
|
|
|
rot(angs,p=[[[-10,7.5,0],[-5,7.5,0]],[[5,7.5,0],[10,7.5,0]]]), info);
|
|
|
|
// line parallel to polygon plane
|
|
|
|
linepll = move([0,0,1],lineon);
|
|
|
|
assert_approx(polygon_line_intersection(poly,linepll,bounded=[true,true]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,linepll,bounded=[true,false]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,linepll,bounded=[false,true]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(poly,linepll,bounded=[false,false]),
|
|
|
|
undef, info);
|
|
|
|
// general case
|
|
|
|
trnsl = [0,0,1];
|
|
|
|
linegnr = move(trnsl,rot(angs,p=[[5,5,5],[3,3,3]]));
|
|
|
|
polygnr = move(trnsl,rot(angs,p=poly0));
|
|
|
|
assert_approx(polygon_line_intersection(polygnr,linegnr,bounded=[true,true]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(polygnr,linegnr,bounded=[true,false]),
|
|
|
|
trnsl, info);
|
|
|
|
assert_approx(polygon_line_intersection(polygnr,linegnr,bounded=[false,true]),
|
|
|
|
undef, info);
|
|
|
|
assert_approx(polygon_line_intersection(polygnr,linegnr,bounded=[false,false]),
|
|
|
|
trnsl, info);
|
2021-09-14 02:09:51 +00:00
|
|
|
|
|
|
|
sq = path3d(square(10));
|
|
|
|
pentagram = 10*path3d(turtle(["move",10,"left",144], repeat=4));
|
|
|
|
for (tran = [ident(4), skew(sxy=1.2)*scale([.9,1,1.2])*yrot(14)*zrot(37)*xrot(9)])
|
|
|
|
{
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[5,5,-1], [5,5,10]])), apply(tran, [5,5,0]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[5,5,1], [5,5,10]])), apply(tran, [5,5,0]));
|
|
|
|
assert(undef==polygon_line_intersection(apply(tran,sq),apply(tran,[[5,5,1], [5,5,10]]),RAY));
|
|
|
|
assert(undef==polygon_line_intersection(apply(tran,sq),apply(tran,[[11,11,-1],[11,11,1]])));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[5,0,-10], [5,0,10]])), apply(tran, [5,0,0]));
|
|
|
|
assert_equal(polygon_line_intersection(apply(tran,sq),apply(tran,[[5,0,1], [5,0,10]]),RAY), undef);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[10,0,1],[10,0,10]])), apply(tran, [10,0,0]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[1,5,0],[9,6,0]])), apply(tran, [[[0,4.875,0],[10,6.125,0]]]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[1,5,0],[9,6,0]]),SEGMENT), apply(tran, [[[1,5,0],[9,6,0]]]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[-1,-1,0],[8,8,0]])), apply(tran, [[[0,0,0],[10,10,0]]]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[-1,-1,0],[8,8,0]]),SEGMENT), apply(tran, [[[0,0,0],[8,8,0]]]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[-1,-1,0],[8,8,0]]),RAY), apply(tran, [[[0,0,0],[10,10,0]]]));
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[-2,4,0], [12,11,0]]),RAY), apply(tran, [[[0,5,0],[10,10,0]]]));
|
|
|
|
assert_equal(polygon_line_intersection(apply(tran,sq),apply(tran,[[-20,0,0],[20,40,0]]),RAY), undef);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,sq),apply(tran,[[-1,0,0],[11,0,0]])), apply(tran, [[[0,0,0],[10,0,0]]]));
|
|
|
|
}
|
|
|
|
assert_approx(polygon_line_intersection(path2d(sq),[[1,5],[9,6]],SEGMENT), [[[1,5],[9,6]]]);
|
|
|
|
assert_approx(polygon_line_intersection(path2d(sq),[[1,5],[9,6]],LINE), [[[0,4.875],[10,6.125]]]);
|
|
|
|
assert_approx(polygon_line_intersection(pentagram,[[50,10,-4],[54,12,4]], nonzero=true), [52,11,0]);
|
|
|
|
assert_equal(polygon_line_intersection(pentagram,[[50,10,-4],[54,12,4]], nonzero=false), undef);
|
|
|
|
assert_approx(polygon_line_intersection(pentagram,[[50,-10,-4],[54,-12,4]], nonzero=true), [52,-11,0]);
|
|
|
|
assert_approx(polygon_line_intersection(pentagram,[[50,-10,-4],[54,-12,4]], nonzero=false), [52,-11,0]);
|
|
|
|
assert_approx(polygon_line_intersection(star(8,step=3,od=10), [[-5,3], [5,3]]),
|
|
|
|
[[[-3.31370849898, 3], [-2.24264068712, 3]],
|
|
|
|
[[-0.828427124746, 3], [0.828427124746, 3]],
|
|
|
|
[[2.24264068712, 3], [3.31370849898, 3]]]);
|
2021-09-15 20:36:03 +00:00
|
|
|
|
|
|
|
tran = skew(sxy=1.2)*scale([.9,1,1.2])*yrot(14)*zrot(37)*xrot(9);
|
|
|
|
|
|
|
|
// assemble multiple edges into one edge
|
|
|
|
assert_approx(polygon_line_intersection(star(r=15,n=8,step=2), [[20,-5],[-5,20]]), [[[15,0],[0,15]]]);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,path3d(star(r=15,n=8,step=2))), apply(tran,[[20,-5,0],[-5,20,0]])), apply(tran,[[[15,0,0],[0,15,0]]]));
|
|
|
|
// line going the other direction
|
|
|
|
assert_approx(polygon_line_intersection(star(r=15,n=8,step=2), [[-5,20],[20,-5]]), [[[0,15],[15,0]]]);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,path3d(star(r=15,n=8,step=2))), apply(tran,[[-5,20,0],[20,-5,0]])),apply(tran, [[[0,15,0],[15,0,0]]]));
|
|
|
|
// single point
|
|
|
|
assert_approx(polygon_line_intersection(hexagon(r=15), [[15,-10],[15,13]], RAY), [[[15,0]]]);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,path3d(hexagon(r=15))), apply(tran,[[15,-10,0],[15,13,0]]), RAY),
|
|
|
|
[[apply(tran,[15,0,0])]]);
|
|
|
|
// two points
|
|
|
|
assert_approx(polygon_line_intersection(star(r=15,n=8,step=3), rot(22.5,p=[[15,-10],[15,20]],cp=[15,0])),
|
|
|
|
[[[15,0]], [[10.6066017178, 10.6066017178]]]);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,path3d(star(r=15,n=8,step=3))), apply(tran,rot(22.5,p=[[15,-10,0],[15,20,0]],cp=[15,0,0]))),
|
|
|
|
[[apply(tran,[15,0,0])], [apply(tran,[10.6066017178, 10.6066017178,0])]]);
|
|
|
|
// two segments and one point
|
|
|
|
star7 = star(r=25,ir=9,n=7);
|
|
|
|
assert_approx(polygon_line_intersection(star7, [left(10,p=star7[8]), right(50,p=star7[8])]),
|
|
|
|
[[[-22.5242216976, 10.8470934779]],
|
|
|
|
[[-5.60077322195, 10.8470934779], [0.997372374838, 10.8470934779]],
|
|
|
|
[[4.61675816681, 10.8470934779], [11.4280421589, 10.8470934779]]]);
|
|
|
|
assert_approx(polygon_line_intersection(apply(tran,path3d(star7)),
|
|
|
|
apply(tran, path3d([left(10,p=star7[8]), right(50,p=star7[8])]))),
|
|
|
|
[[apply(tran,[-22.5242216976, 10.8470934779,0])],
|
|
|
|
apply(tran,[[-5.60077322195, 10.8470934779,0], [0.997372374838, 10.8470934779,0]]),
|
|
|
|
apply(tran,[[4.61675816681, 10.8470934779,0], [11.4280421589, 10.8470934779,0]])]);
|
2020-08-29 02:07:10 +00:00
|
|
|
}
|
|
|
|
*test_polygon_line_intersection();
|
|
|
|
|
|
|
|
|
2019-05-02 02:28:02 +00:00
|
|
|
module test_coplanar() {
|
2020-08-16 22:33:11 +00:00
|
|
|
assert(coplanar([ [5,5,1],[0,0,1],[-1,-1,1] ]) == false);
|
|
|
|
assert(coplanar([ [5,5,1],[0,0,0],[-1,-1,1] ]) == true);
|
|
|
|
assert(coplanar([ [0,0,0],[1,0,1],[1,1,1], [0,1,2] ]) == false);
|
|
|
|
assert(coplanar([ [0,0,0],[1,0,1],[1,1,2], [0,1,1] ]) == true);
|
2021-04-10 20:07:23 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_coplanar();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2021-09-10 22:16:42 +00:00
|
|
|
module test_above_plane() {
|
2020-05-30 02:04:34 +00:00
|
|
|
plane = plane3pt([0,0,0], [0,10,10], [10,0,10]);
|
2021-09-10 22:16:42 +00:00
|
|
|
assert(above_plane(plane, [5,5,10]) == false);
|
|
|
|
assert(above_plane(plane, [-5,0,0]) == true);
|
|
|
|
assert(above_plane(plane, [5,0,0]) == false);
|
|
|
|
assert(above_plane(plane, [0,-5,0]) == true);
|
|
|
|
assert(above_plane(plane, [0,5,0]) == false);
|
|
|
|
assert(above_plane(plane, [0,0,5]) == true);
|
|
|
|
assert(above_plane(plane, [0,0,-5]) == false);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2021-09-10 22:16:42 +00:00
|
|
|
*test_above_plane();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2019-10-30 05:47:38 +00:00
|
|
|
module test_is_path() {
|
2020-09-09 08:37:31 +00:00
|
|
|
assert(is_path([[1,2,3],[4,5,6]]));
|
|
|
|
assert(is_path([[1,2,3],[4,5,6],[7,8,9]]));
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(!is_path(123));
|
|
|
|
assert(!is_path("foo"));
|
|
|
|
assert(!is_path(true));
|
|
|
|
assert(!is_path([]));
|
|
|
|
assert(!is_path([[]]));
|
|
|
|
assert(!is_path([["foo","bar","baz"]]));
|
|
|
|
assert(!is_path([[1,2,3]]));
|
|
|
|
assert(!is_path([["foo","bar","baz"],["qux","quux","quuux"]]));
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_is_path();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_is_closed_path() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(!is_closed_path([[1,2,3],[4,5,6],[1,8,9]]));
|
|
|
|
assert(is_closed_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]));
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_is_closed_path();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_close_path() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(close_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
|
|
|
assert(close_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9],[1,2,3]]);
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_close_path();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_cleanup_path() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(cleanup_path([[1,2,3],[4,5,6],[1,8,9]]) == [[1,2,3],[4,5,6],[1,8,9]]);
|
|
|
|
assert(cleanup_path([[1,2,3],[4,5,6],[1,8,9],[1,2,3]]) == [[1,2,3],[4,5,6],[1,8,9]]);
|
2019-10-30 05:47:38 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_cleanup_path();
|
2019-10-30 05:47:38 +00:00
|
|
|
|
|
|
|
|
2019-10-31 01:41:18 +00:00
|
|
|
module test_polygon_area() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(approx(polygon_area([[1,1],[-1,1],[-1,-1],[1,-1]]), 4));
|
2021-03-25 11:51:10 +00:00
|
|
|
assert(approx(polygon_area(circle(r=50,$fn=1000),signed=true), -PI*50*50, eps=0.1));
|
2021-04-10 20:07:23 +00:00
|
|
|
assert(approx(polygon_area(rot([13,27,75],
|
|
|
|
p=path3d(circle(r=50,$fn=1000),fill=23)),
|
2021-09-10 22:16:42 +00:00
|
|
|
signed=true), PI*50*50, eps=0.1));
|
2021-09-10 22:02:56 +00:00
|
|
|
assert(abs(triangle_area([0,0], [0,10], [10,0]) + 50) < EPSILON);
|
|
|
|
assert(abs(triangle_area([0,0], [0,10], [0,15])) < EPSILON);
|
|
|
|
assert(abs(triangle_area([0,0], [10,0], [0,10]) - 50) < EPSILON);
|
|
|
|
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_polygon_area();
|
|
|
|
|
|
|
|
|
2021-09-12 03:11:18 +00:00
|
|
|
module test_is_polygon_convex() {
|
|
|
|
assert(is_polygon_convex([[1,1],[-1,1],[-1,-1],[1,-1]]));
|
|
|
|
assert(is_polygon_convex(circle(r=50,$fn=1000)));
|
|
|
|
assert(is_polygon_convex(rot([50,120,30], p=path3d(circle(1,$fn=50)))));
|
|
|
|
assert(!is_polygon_convex([[1,1],[0,0],[-1,1],[-1,-1],[1,-1]]));
|
|
|
|
assert(!is_polygon_convex([for (i=[0:36]) let(a=-i*10) (10+i)*[cos(a),sin(a)]])); // spiral
|
2020-08-16 22:33:11 +00:00
|
|
|
}
|
2021-09-12 03:11:18 +00:00
|
|
|
*test_is_polygon_convex();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_polygon_shift() {
|
2020-05-30 02:04:34 +00:00
|
|
|
path = [[1,1],[-1,1],[-1,-1],[1,-1]];
|
|
|
|
assert(polygon_shift(path,1) == [[-1,1],[-1,-1],[1,-1],[1,1]]);
|
|
|
|
assert(polygon_shift(path,2) == [[-1,-1],[1,-1],[1,1],[-1,1]]);
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_polygon_shift();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_polygon_shift_to_closest_point() {
|
2020-05-30 02:04:34 +00:00
|
|
|
path = [[1,1],[-1,1],[-1,-1],[1,-1]];
|
|
|
|
assert(polygon_shift_to_closest_point(path,[1.1,1.1]) == [[1,1],[-1,1],[-1,-1],[1,-1]]);
|
|
|
|
assert(polygon_shift_to_closest_point(path,[-1.1,1.1]) == [[-1,1],[-1,-1],[1,-1],[1,1]]);
|
|
|
|
assert(polygon_shift_to_closest_point(path,[-1.1,-1.1]) == [[-1,-1],[1,-1],[1,1],[-1,1]]);
|
|
|
|
assert(polygon_shift_to_closest_point(path,[1.1,-1.1]) == [[1,-1],[1,1],[-1,1],[-1,-1]]);
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_polygon_shift_to_closest_point();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
2020-08-16 22:33:11 +00:00
|
|
|
module test_reindex_polygon() {
|
|
|
|
pent = subdivide_path([for(i=[0:4])[sin(72*i),cos(72*i)]],5);
|
|
|
|
circ = circle($fn=5,r=2.2);
|
|
|
|
assert_approx(reindex_polygon(circ,pent), [[0.951056516295,0.309016994375],[0.587785252292,-0.809016994375],[-0.587785252292,-0.809016994375],[-0.951056516295,0.309016994375],[0,1]]);
|
|
|
|
poly = [[-1,1],[-1,-1],[1,-1],[1,1],[0,0]];
|
|
|
|
ref = [for(i=[0:4])[sin(72*i),cos(72*i)]];
|
|
|
|
assert_approx(reindex_polygon(ref,poly),[[0,0],[1,1],[1,-1],[-1,-1],[-1,1]]);
|
|
|
|
}
|
|
|
|
*test_reindex_polygon();
|
|
|
|
|
|
|
|
|
|
|
|
module test_align_polygon() {
|
|
|
|
pentagon = subdivide_path(pentagon(side=2),10);
|
|
|
|
hexagon = subdivide_path(hexagon(side=2.7),10);
|
|
|
|
aligned = [[2.7,0],[2.025,-1.16913429511],[1.35,-2.33826859022],
|
|
|
|
[-1.35,-2.33826859022],[-2.025,-1.16913429511],[-2.7,0],
|
|
|
|
[-2.025,1.16913429511],[-1.35,2.33826859022],[1.35,2.33826859022],
|
|
|
|
[2.025,1.16913429511]];
|
|
|
|
assert_approx(align_polygon(pentagon,hexagon,[0:10:359]), aligned);
|
|
|
|
aligned2 = [[1.37638192047,0],[1.37638192047,-1],[0.425325404176,-1.30901699437],
|
|
|
|
[-0.525731112119,-1.61803398875],[-1.11351636441,-0.809016994375],
|
|
|
|
[-1.7013016167,0],[-1.11351636441,0.809016994375],
|
|
|
|
[-0.525731112119,1.61803398875],[0.425325404176,1.30901699437],
|
|
|
|
[1.37638192047,1]];
|
|
|
|
assert_approx(align_polygon(hexagon,pentagon,[0:10:359]), aligned2);
|
|
|
|
}
|
|
|
|
*test_align_polygon();
|
|
|
|
|
|
|
|
|
|
|
|
module test_noncollinear_triple() {
|
|
|
|
assert(noncollinear_triple([[1,1],[2,2],[3,3],[4,4],[4,5],[5,6]]) == [0,5,3]);
|
|
|
|
assert(noncollinear_triple([[1,1],[2,2],[8,3],[4,4],[4,5],[5,6]]) == [0,2,5]);
|
2020-07-28 22:06:57 +00:00
|
|
|
u = unit([5,3]);
|
2020-08-16 22:33:11 +00:00
|
|
|
assert_equal(noncollinear_triple([for(i = [2,3,4,5,7,12,15]) i * u], error=false),[]);
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_noncollinear_triple();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
2021-04-05 15:00:07 +00:00
|
|
|
|
2020-07-06 23:15:32 +00:00
|
|
|
module test_centroid() {
|
|
|
|
$fn = 24;
|
|
|
|
assert_approx(centroid(circle(d=100)), [0,0]);
|
2021-04-07 02:25:40 +00:00
|
|
|
assert_approx(centroid(rect([40,60],rounding=10,anchor=LEFT)), [20,0]);
|
2020-07-06 23:15:32 +00:00
|
|
|
assert_approx(centroid(rect([40,60],rounding=10,anchor=FWD)), [0,30]);
|
2021-03-25 11:51:10 +00:00
|
|
|
poly = move([1,2.5,3.1],p=rot([12,49,24], p=path3d(circle(10,$fn=33))));
|
2020-08-16 22:33:11 +00:00
|
|
|
assert_approx(centroid(poly), [1,2.5,3.1]);
|
2020-07-06 23:15:32 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_centroid();
|
2019-10-25 22:17:55 +00:00
|
|
|
|
|
|
|
|
2019-05-02 02:28:02 +00:00
|
|
|
module test_simplify_path() {
|
|
|
|
path = [[-20,-20], [-10,-20], [0,-10], [10,0], [20,10], [20,20], [15,30]];
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(simplify_path(path) == [[-20,-20], [-10,-20], [20,10], [20,20], [15,30]]);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_simplify_path();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_simplify_path_indexed() {
|
|
|
|
pts = [[10,0], [0,-10], [20,20], [20,10], [-20,-20], [15,30], [-10,-20]];
|
|
|
|
path = [4,6,1,0,3,2,5];
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(simplify_path_indexed(pts, path) == [4,6,3,2,5]);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_simplify_path_indexed();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_point_in_polygon() {
|
2020-05-30 02:04:34 +00:00
|
|
|
poly = [for (a=[0:30:359]) 10*[cos(a),sin(a)]];
|
2020-08-20 21:42:24 +00:00
|
|
|
poly2 = [ [-3,-3],[2,-3],[2,1],[-1,1],[-1,-1],[1,-1],[1,2],[-3,2] ];
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(point_in_polygon([0,0], poly) == 1);
|
|
|
|
assert(point_in_polygon([20,0], poly) == -1);
|
2021-03-25 11:51:10 +00:00
|
|
|
assert(point_in_polygon([20,0], poly,nonzero=false) == -1);
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(point_in_polygon([5,5], poly) == 1);
|
|
|
|
assert(point_in_polygon([-5,5], poly) == 1);
|
|
|
|
assert(point_in_polygon([-5,-5], poly) == 1);
|
|
|
|
assert(point_in_polygon([5,-5], poly) == 1);
|
2021-03-25 11:51:10 +00:00
|
|
|
assert(point_in_polygon([5,-5], poly,nonzero=false,eps=EPSILON) == 1);
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(point_in_polygon([-10,-10], poly) == -1);
|
|
|
|
assert(point_in_polygon([10,0], poly) == 0);
|
|
|
|
assert(point_in_polygon([0,10], poly) == 0);
|
|
|
|
assert(point_in_polygon([0,-10], poly) == 0);
|
2021-03-25 11:51:10 +00:00
|
|
|
assert(point_in_polygon([0,-10], poly,nonzero=false) == 0);
|
|
|
|
assert(point_in_polygon([0,0], poly2,nonzero=true) == 1);
|
|
|
|
assert(point_in_polygon([0,1], poly2,nonzero=true) == 0);
|
|
|
|
assert(point_in_polygon([0,1], poly2,nonzero=false) == 0);
|
|
|
|
assert(point_in_polygon([1,0], poly2,nonzero=false) == 0);
|
|
|
|
assert(point_in_polygon([0,0], poly2,nonzero=false,eps=EPSILON) == -1);
|
2019-05-02 02:28:02 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_point_in_polygon();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
|
|
|
|
2019-10-31 01:41:18 +00:00
|
|
|
|
2021-09-11 22:48:23 +00:00
|
|
|
module test_is_polygon_clockwise() {
|
|
|
|
assert(is_polygon_clockwise([[-1,1],[1,1],[1,-1],[-1,-1]]));
|
|
|
|
assert(!is_polygon_clockwise([[1,1],[-1,1],[-1,-1],[1,-1]]));
|
|
|
|
assert(is_polygon_clockwise(circle(d=100)));
|
|
|
|
assert(is_polygon_clockwise(square(100)));
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2021-09-11 22:48:23 +00:00
|
|
|
*test_is_polygon_clockwise();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_clockwise_polygon() {
|
2020-05-30 02:04:34 +00:00
|
|
|
path = circle(d=100);
|
|
|
|
rpath = concat([path[0]], reverse(select(path,1,-1)));
|
|
|
|
assert(clockwise_polygon(path) == path);
|
|
|
|
assert(clockwise_polygon(rpath) == path);
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_clockwise_polygon();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
module test_ccw_polygon() {
|
2020-05-30 02:04:34 +00:00
|
|
|
path = circle(d=100);
|
|
|
|
rpath = concat([path[0]], reverse(select(path,1,-1)));
|
|
|
|
assert(ccw_polygon(path) == rpath);
|
|
|
|
assert(ccw_polygon(rpath) == rpath);
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_ccw_polygon();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
|
|
|
|
2019-11-18 02:19:55 +00:00
|
|
|
module test_reverse_polygon() {
|
2020-05-30 02:04:34 +00:00
|
|
|
path = circle(d=100);
|
|
|
|
rpath = concat([path[0]], reverse(select(path,1,-1)));
|
|
|
|
assert(reverse_polygon(path) == rpath);
|
|
|
|
assert(reverse_polygon(rpath) == path);
|
2019-11-18 02:19:55 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_reverse_polygon();
|
2019-11-18 02:19:55 +00:00
|
|
|
|
|
|
|
|
2019-10-31 01:41:18 +00:00
|
|
|
module test_is_region() {
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_region([circle(d=10),square(10)]));
|
|
|
|
assert(is_region([circle(d=10),square(10),circle(d=50)]));
|
|
|
|
assert(is_region([square(10)]));
|
|
|
|
assert(!is_region([]));
|
|
|
|
assert(!is_region(23));
|
|
|
|
assert(!is_region(true));
|
|
|
|
assert(!is_region("foo"));
|
2019-10-31 01:41:18 +00:00
|
|
|
}
|
2020-08-16 22:33:11 +00:00
|
|
|
*test_is_region();
|
2019-10-31 01:41:18 +00:00
|
|
|
|
2021-06-21 19:19:07 +00:00
|
|
|
module test_convex_distance() {
|
2021-06-21 19:43:12 +00:00
|
|
|
// 2D
|
2021-06-21 19:19:07 +00:00
|
|
|
c1 = circle(10,$fn=24);
|
2021-06-21 19:43:12 +00:00
|
|
|
c2 = move([15,0], p=c1);
|
|
|
|
assert(convex_distance(c1, c2)==0);
|
|
|
|
c3 = move([22,0],c1);
|
|
|
|
assert_approx(convex_distance(c1, c3),2);
|
|
|
|
// 3D
|
2021-06-21 19:19:07 +00:00
|
|
|
s1 = sphere(10,$fn=4);
|
2021-06-21 19:43:12 +00:00
|
|
|
s2 = move([15,0], p=s1);
|
|
|
|
assert_approx(convex_distance(s1[0], s2[0]), 0.857864376269);
|
|
|
|
s3 = move([25.3,0],s1);
|
|
|
|
assert_approx(convex_distance(s1[0], s3[0]), 11.1578643763);
|
|
|
|
s4 = move([30,25],s1);
|
|
|
|
assert_approx(convex_distance(s1[0], s4[0]), 28.8908729653);
|
|
|
|
s5 = move([10*sqrt(2),0],s1);
|
|
|
|
assert_approx(convex_distance(s1[0], s5[0]), 0);
|
|
|
|
}
|
|
|
|
*test_convex_distance();
|
|
|
|
|
|
|
|
module test_convex_collision() {
|
|
|
|
// 2D
|
|
|
|
c1 = circle(10,$fn=24);
|
|
|
|
c2 = move([15,0], p=c1);
|
|
|
|
assert(convex_collision(c1, c2));
|
|
|
|
c3 = move([22,0],c1);
|
|
|
|
assert(!convex_collision(c1, c3));
|
|
|
|
// 3D
|
|
|
|
s1 = sphere(10,$fn=4);
|
|
|
|
s2 = move([15,0], p=s1);
|
|
|
|
assert(!convex_collision(s1[0], s2[0]));
|
|
|
|
s3 = move([25.3,0],s1);
|
|
|
|
assert(!convex_collision(s1[0], s3[0]));
|
|
|
|
s4 = move([5,0],s1);
|
|
|
|
assert(convex_collision(s1[0], s4[0]));
|
|
|
|
s5 = move([10*sqrt(2),0],s1);
|
|
|
|
assert(convex_collision(s1[0], s5[0]));
|
2021-06-21 19:19:07 +00:00
|
|
|
}
|
|
|
|
*test_convex_distance();
|
2019-05-02 02:28:02 +00:00
|
|
|
|
2020-05-30 02:04:34 +00:00
|
|
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|