public static bool isinside(Geo.Tri t, Geo.Point p) { // point in triangle test // a new Tri projected onto the xy plane: Geo.Point p1 = new Geo.Point(t.p[0].x, t.p[0].y, 0); Geo.Point p2 = new Geo.Point(t.p[1].x, t.p[1].y, 0); Geo.Point p3 = new Geo.Point(t.p[2].x, t.p[2].y, 0); Geo.Point pt = new Geo.Point(p.x, p.y, 0); bool b1 = isright(p1, p2, pt); bool b2 = isright(p3, p1, pt); bool b3 = isright(p2, p3, pt); if ((b1) && (b2) && (b3)) { return true; } else if ((!b1) && (!b2) && (!b3)) { return true; } else { return false; } } // end isinside()
// test for bounding box function public static void bbox_test(GLWindow g) { // draw a triangle Geo.Point p1 = new Geo.Point(0.1, 0.1, 0); Geo.Point p2 = new Geo.Point(0.8, 0.3, 0); Geo.Point p3 = new Geo.Point(0.2, 0.6, 0); GeoLine l1 = new GeoLine(p1, p2); GeoLine l2 = new GeoLine(p1, p3); GeoLine l3 = new GeoLine(p3, p2); l1.color = System.Drawing.Color.RoyalBlue; l2.color = System.Drawing.Color.RoyalBlue; l3.color = System.Drawing.Color.RoyalBlue; g.addGeom(l1); g.addGeom(l2); g.addGeom(l3); // create triangle and calculate bounding box Geo.Tri t = new Geo.Tri(p1, p2, p3); t.calc_bbox(); Geo.Point a = new Geo.Point(t.bb.minx, t.bb.miny, 0); Geo.Point b = new Geo.Point(t.bb.maxx, t.bb.miny, 0); Geo.Point c = new Geo.Point(t.bb.maxx, t.bb.maxy, 0); Geo.Point d = new Geo.Point(t.bb.minx, t.bb.maxy, 0); GeoLine h1 = new GeoLine(a, b); GeoLine h2 = new GeoLine(b, c); GeoLine h3 = new GeoLine(c, d); GeoLine h4 = new GeoLine(d, a); h1.color = System.Drawing.Color.Red; h2.color = System.Drawing.Color.Red; h3.color = System.Drawing.Color.Red; h4.color = System.Drawing.Color.Red; g.addGeom(h1); g.addGeom(h2); g.addGeom(h3); g.addGeom(h4); // check that the points are OK GeoPoint v1 = new GeoPoint(t.bb.minx, t.bb.miny, 0); v1.color = System.Drawing.Color.Green; g.addGeom(v1); GeoPoint v2 = new GeoPoint(t.bb.maxx, t.bb.maxy, 0); v2.color = System.Drawing.Color.Azure; g.addGeom(v2); }
// testing that the isinside function works OK public static void isinside_test(GLWindow g) { Random r = new Random(); // generate lots of random points int N = 100; List <GeoPoint> points = new List <GeoPoint>(); for (int n = 0; n < N; n++) { GeoPoint p = new GeoPoint(0.001 * (float)r.Next(0, 1000), 0.001 * (float)r.Next(0, 1000), 0); points.Add(p); } // draw a triangle Geo.Point p1 = new Geo.Point(0.1, 0.1, 0); Geo.Point p2 = new Geo.Point(0.8, 0.1, 0); Geo.Point p3 = new Geo.Point(0.2, 0.6, 0); GeoLine l1 = new GeoLine(p1, p2); GeoLine l2 = new GeoLine(p1, p3); GeoLine l3 = new GeoLine(p3, p2); l1.color = System.Drawing.Color.RoyalBlue; l2.color = System.Drawing.Color.RoyalBlue; l3.color = System.Drawing.Color.RoyalBlue; g.addGeom(l1); g.addGeom(l2); g.addGeom(l3); // p.color = System.Drawing.Color.Aqua; // draw points Geo.Tri t = new Geo.Tri(p2, p3, p1); foreach (GeoPoint p in points) { if (DropCutter.isinside(t, p.p)) { p.color = System.Drawing.Color.Aqua; } else { p.color = System.Drawing.Color.Red; } g.addGeom(p); } }
static public STLSurf Load(System.IO.StreamReader fs) { // Here's where autodetection will be provided for loading binary stl files and by wrapping STLA(scii) and STLB(inary) // but for now as only one format is provided, not bothering with it, we need to define a object format for handling file loading/saving // System.IO.StreamReader fs = new System.IO.StreamReader(FileName); STLSurf surf = new STLSurf(); int state = 0; int counter = 0; string[] data; Geo.Tri triangle = new Geo.Tri(); Vector normal = new Vector(); System.Globalization.CultureInfo locale = new System.Globalization.CultureInfo("en-GB"); int n_triangles = 0; while (!fs.EndOfStream) { data = fs.ReadLine().TrimStart(' ').Split(' '); switch (state) { case 0: if (data[0].Equals("solid")) { surf.name = data[1]; state = 1; // continue readingx } break; case 1: if (data[0].Equals("facet")) { normal.x = double.Parse(data[2], locale); normal.y = double.Parse(data[3], locale); normal.z = double.Parse(data[4], locale); triangle = new Geo.Tri(normal); counter = 0; state = 2; } break; case 2: if (data[0].Equals("vertex")) { if (counter <= 2) { triangle.p[counter].x = double.Parse(data[1], locale); triangle.p[counter].y = double.Parse(data[2], locale); triangle.p[counter].z = double.Parse(data[3], locale); // System.Console.WriteLine("STLReader: added point" + triangle.p[counter]); // System.Console.ReadKey(); counter++; } } else if (data[0].Equals("endfacet")) { if (counter == 3) { surf.AddTriangle(triangle); n_triangles += 1; } state = 1; } break; } } fs.Close(); System.Console.WriteLine("STLReader: read {0} triangles!", n_triangles); return(surf); }
// testing that the isinside function works OK public static void isinside_test(GLWindow g) { Random r = new Random(); // generate lots of random points int N = 100; List<GeoPoint> points = new List<GeoPoint>(); for (int n = 0; n < N; n++) { GeoPoint p = new GeoPoint(0.001 * (float)r.Next(0, 1000), 0.001 * (float)r.Next(0, 1000), 0); points.Add(p); } // draw a triangle Geo.Point p1 = new Geo.Point(0.1, 0.1, 0); Geo.Point p2 = new Geo.Point(0.8, 0.1, 0); Geo.Point p3 = new Geo.Point(0.2, 0.6, 0); GeoLine l1 = new GeoLine(p1, p2); GeoLine l2 = new GeoLine(p1, p3); GeoLine l3 = new GeoLine(p3, p2); l1.color = System.Drawing.Color.RoyalBlue; l2.color = System.Drawing.Color.RoyalBlue; l3.color = System.Drawing.Color.RoyalBlue; g.addGeom(l1); g.addGeom(l2); g.addGeom(l3); // p.color = System.Drawing.Color.Aqua; // draw points Geo.Tri t = new Geo.Tri(p2, p3, p1); foreach (GeoPoint p in points) { if (DropCutter.isinside(t,p.p)) p.color = System.Drawing.Color.Aqua; else p.color = System.Drawing.Color.Red; g.addGeom(p); } }
} // end VertexTest public static double? FacetTest(Cutter cu, Geo.Point e, Geo.Tri t) { // local copy of the surface normal t.recalc_normals(); // don't trust the pre-calculated normal! calculate it separately here. Vector n = new Vector(t.n.x, t.n.y, t.n.z); Geo.Point cc; if (n.z == 0) { // vertical plane, can't touch cutter against that! return null; } else if (n.z < 0) { // flip the normal so it points up (? is this always required?) n = -1*n; } // define plane containing facet double a = n.x; double b = n.y; double c = n.z; double d = - n.x * t.p[0].x - n.y * t.p[0].y - n.z * t.p[0].z; // the z-direction normal is a special case (?required?) // in debug phase, see if this is a useful case! if ((a == 0) && (b == 0)) { // System.Console.WriteLine("facet-test:z-dir normal case!"); e.z = t.p[0].z; cc = new Geo.Point(e.x,e.y,e.z); if (isinside(t, cc)) { // System.Console.WriteLine("facet-test:z-dir normal case!, returning {0}",e.z); // System.Console.ReadKey(); return e.z; } else return null; } // System.Console.WriteLine("facet-test:general case!"); // facet test general case // uses trigonometry, so might be too slow? // flat endmill and ballnose should be simple to do without trig // toroidal case might require offset-ellipse idea? /* theta = asin(c); zf= -d/c - (a*xe+b*ye)/c+ (R-r)/tan(theta) + r/sin(theta) -r; e=[xe ye zf]; u=[0 0 1]; rc=e + ((R-r)*tan(theta)+r)*u - ((R-r)/cos(theta) + r)*n; t=isinside(p1,p2,p3,rc); */ double theta = Math.Asin(c); double zf = -d/c - (a*e.x+b*e.y)/c + (cu.R-cu.r)/Math.Tan(theta) + cu.r/Math.Sin(theta) - cu.r; Vector ve = new Vector(e.x,e.y,zf); Vector u = new Vector(0,0,1); Vector rc = new Vector(); rc = ve +((cu.R-cu.r)*Math.Tan(theta)+cu.r)*u - ((cu.R-cu.r)/Math.Cos(theta)+cu.r)*n; /* if (rc.z > 1000) System.Console.WriteLine("z>1000 !"); */ cc = new Geo.Point(rc.x, rc.y, rc.z); // check that CC lies in plane: // a*rc(1)+b*rc(2)+c*rc(3)+d double test = a * cc.x + b * cc.y + c * cc.z + d; if (test > 0.000001) System.Console.WriteLine("FacetTest ERROR! CC point not in plane"); if (isinside(t, cc)) { if (Math.Abs(zf) > 100) { System.Console.WriteLine("serious problem... at" +e.x + "," + e.y); } return zf; } else return null; } // end FacetTest
public static STLSurf Load(System.IO.StreamReader fs) { // Here's where autodetection will be provided for loading binary stl files and by wrapping STLA(scii) and STLB(inary) // but for now as only one format is provided, not bothering with it, we need to define a object format for handling file loading/saving // System.IO.StreamReader fs = new System.IO.StreamReader(FileName); STLSurf surf = new STLSurf(); int state = 0; int counter = 0; string[] data; Geo.Tri triangle = new Geo.Tri(); Vector normal = new Vector(); System.Globalization.CultureInfo locale = new System.Globalization.CultureInfo("en-GB"); int n_triangles=0; while ( !fs.EndOfStream ) { data = fs.ReadLine().TrimStart(' ').Split(' '); switch (state) { case 0: if (data[0].Equals("solid")) { surf.name = data[1]; state = 1; // continue readingx } break; case 1: if (data[0].Equals("facet")) { normal.x = double.Parse(data[2], locale); normal.y = double.Parse(data[3], locale); normal.z = double.Parse(data[4], locale); triangle = new Geo.Tri(normal); counter = 0; state = 2; } break; case 2: if (data[0].Equals("vertex")) { if ( counter <= 2 ) { triangle.p[counter].x = double.Parse(data[1], locale); triangle.p[counter].y = double.Parse(data[2], locale); triangle.p[counter].z = double.Parse(data[3], locale); // System.Console.WriteLine("STLReader: added point" + triangle.p[counter]); // System.Console.ReadKey(); counter++; } } else if (data[0].Equals("endfacet")) { if (counter == 3) { surf.AddTriangle(triangle); n_triangles += 1; } state = 1; } break; } } fs.Close(); System.Console.WriteLine("STLReader: read {0} triangles!",n_triangles); return (surf); }