public static CompoundSolid Crosscut_Or_Rip(CompoundSolid sol, HalfEdge he, Inches distAlongEdge, double miter, double tilt) { Face f = he.face; // TODO fix these names string[] fnames = new string[] { "miter_top", "miter_right", "miter_left", "miter_bottom", "miter", // the primary face name which gets left "miter_below", }; xyz nrml = f.UnitNormal(); xyz origin = he.to + he.GetInwardNormal() * distAlongEdge; // vx is in the direction of the cut xyz vx = ut.RotateUnitVector(-he.UnitVector(), -miter, nrml); // now rotate nrml for tilt nrml = ut.RotateUnitVector(nrml, tilt, vx); // origin is going to be the corner of the cutter box. // right now it is sitting on the face. we need to // move it further away. calculate intersections with // the boundingbox of the compoundsolid as a whole. BoundingBox3d bb = sol.GetBoundingBox(); double d_vx = bb.IntersectRay_Planes_Max(origin, -vx); double d_nrml = bb.IntersectRay_Planes_Max(origin, nrml); // TODO this approach creates a bb which is too big. do we care? // now move origin far enough back behind the face origin.subtract_in_place((d_vx + 2) * vx); // and up above the face origin = origin + (d_nrml + 2) * nrml; xyz vy = xyz.cross(nrml, vx).normalize_in_place(); xyz vz = -nrml; d_vx = bb.IntersectRay_Planes_Max(origin, vx); double d_vy = bb.IntersectRay_Planes_Max(origin, vy); double d_vz = bb.IntersectRay_Planes_Max(origin, vz); // now calculate proper sizes for the cutter double dx = d_vx + 2; double dy = d_vy + 2; double dz = d_vz + 2; Solid cutter = CreateCutter_Box(string.Format("{0}_{1}", f.name, he.Opposite().face.name), origin, vx, nrml, new xyz(dx, dy, dz), fnames); //sol = sol.Clone(); //sol.AddSub(cutter); //return sol; return(bool3d.Subtract(sol, cutter)); }
private static void CreateFaceLabel(Viewport3D myVP, Face f, TranslateTransform3D ttmove) { HalfEdge he = f.FindLongestEdge(); xyz p1 = he.Center(); xyz p2 = f.Measure(he, p1); xyz v = p2 - p1; double dist = v.magnitude(); xyz c = p1 + v / 2; c += f.UnitNormal() * .001; Point3D center = wpfmisc.fixPoint(c); Vector3D over = wpfmisc.fixVector(he.UnitVector()); Vector3D up = wpfmisc.fixVector(he.GetInwardNormal()); double height; if (dist <= 1) { height = dist / 3; } else if (dist < 10) { height = 1; } else { height = 2; } // TODO the following isn't a very pretty hack if (f.name.Length * height > he.Length()) { height = he.Length() / f.name.Length; } ModelVisual3D mv3d = wpfmisc.CreateTextLabel3D(f.name, Brushes.Black, false, height, center, over, up); if (ttmove != null) { mv3d.Transform = ttmove; } myVP.Children.Add(mv3d); }
public static void Edges(IOrient s2, Face f1, Face f2, HalfEdge he1, HalfEdge he2, EdgeAlignment align, double offset1, double offset2, bool reversed) { xyz v1; xyz v2; xyz uv1 = (he1.to - he1.from).normalize_in_place(); Debug.Assert( (align == EdgeAlignment.Center) || (align == EdgeAlignment.Right) || (align == EdgeAlignment.Left) ); // move the solid to match up two points if (align == EdgeAlignment.Center) { v1 = he1.Center(); if (!fp.eq_inches(offset1, 0)) { v1 += (offset1 * uv1); } v2 = he2.Center(); } else if (align == EdgeAlignment.Right) { v1 = he1.to; if (!fp.eq_inches(offset1, 0)) { v1 -= (offset1 * uv1); } v2 = he2.from; } else // left { v1 = he1.from; if (!fp.eq_inches(offset1, 0)) { v1 += (offset1 * uv1); } v2 = he2.to; } if (!fp.eq_inches(offset2, 0)) { xyz uv1perp = -(he1.GetInwardNormal()); v1 += (offset2 * uv1perp); } xyz tv = v1 - v2; s2.Translate(tv.x, tv.y, tv.z); if (reversed) { RotateSoFacesAreParallelAndSameDir(s2, f1, f2, v1); } else { RotateSoFacesAreParallelAndOpposite(s2, f1, f2, v1); } // now rotate around origin = f1.MainLoop[0].to and vector = n1 to align the other points xyz q1 = he1.UnitVector(); xyz q2 = he2.UnitVector(); if (reversed) { q2 = -q2; } if (fp.eq_unitvec(q1, q2)) { s2.Rotate(-1, 0, v1, f1.UnitNormal()); } else if (fp.eq_unitvec(q1, -q2)) { // do nothing. this is perfect. } else { double dot = xyz.dot(q1, q2); xyz kp = xyz.cross(q2, q1).normalize_in_place(); s2.Rotate(-dot, -Math.Sqrt(1 - dot * dot), v1, kp); } }