static public Glulam CreateGlulamFromBeamGeometry2(Curve curve, Mesh beam, out double true_width, out double true_height, out double true_length, double extra = 0.0) { Mesh mm = curve.MapToCurveSpace(beam); BoundingBox bb = mm.GetBoundingBox(true); double x = bb.Center.X; double y = bb.Center.Y; double tmin, tmax; curve.LengthParameter(bb.Min.Z, out tmin); curve.LengthParameter(bb.Max.Z, out tmax); Plane twist = Plane.WorldXY; Polyline ch; mm = mm.FitToAxes(Plane.WorldXY, out ch, ref twist); bb = mm.GetBoundingBox(true); double dx = bb.Max.X - bb.Min.X; double dy = bb.Max.Y - bb.Min.Y; Plane cp; curve.PerpendicularFrameAt(tmin, out cp); double angle = Vector3d.VectorAngle(Vector3d.XAxis, twist.XAxis); int sign = Math.Sign(twist.YAxis * Vector3d.XAxis); Curve[] segments = curve.Split(new double[] { tmin, tmax }); if (segments.Length == 3) { curve = segments[1]; } else { curve = segments[0]; } Beam b = new Beam(curve, null, new Plane[] { cp }); //curve = b.CreateOffsetCurve(-x, -y); curve = b.CreateOffsetCurve(x, y); curve = curve.Extend(CurveEnd.Both, extra, CurveExtensionStyle.Smooth); cp.Transform(Rhino.Geometry.Transform.Rotation(angle * sign, cp.ZAxis, cp.Origin)); GlulamData data = GlulamData.FromCurveLimits(curve, dx + extra * 2, dy + extra * 2, new Plane[] { cp }); true_length = curve.GetLength(); true_width = dx + extra * 2; true_height = dy + extra * 2; return(Glulam.CreateGlulam(curve, new Plane[] { cp }, data)); }
/// <summary> /// Glulam factory methods. /// </summary> /// <param name="curve">Input curve.</param> /// <param name="planes">Input orientation planes.</param> /// <param name="data">Input glulam data.</param> /// <returns>New glulam.</returns> static public Glulam CreateGlulam(Curve curve, Plane[] planes = null, GlulamData data = null) { if (data == null) { data = GlulamData.FromCurveLimits(curve); } Glulam glulam; if (planes == null || planes.Length < 1) // if there are no planes defined, create defaults { Plane p; if (curve.IsLinear(Tolerance)) { curve.PerpendicularFrameAt(curve.Domain.Min, out p); glulam = new StraightGlulam(curve, new Plane[] { p }); } else if (curve.IsPlanar(Tolerance)) { curve.TryGetPlane(out p, Tolerance); glulam = new SingleCurvedGlulam(curve, new Plane[] { new Plane( curve.PointAtStart, p.ZAxis, Vector3d.CrossProduct( curve.TangentAtStart, p.ZAxis ) ), new Plane( curve.PointAtEnd, p.ZAxis, Vector3d.CrossProduct( curve.TangentAtEnd, p.ZAxis ) ) }); } else { Plane start, end; curve.PerpendicularFrameAt(curve.Domain.Min, out start); curve.PerpendicularFrameAt(curve.Domain.Max, out end); glulam = new DoubleCurvedGlulam(curve, new Plane[] { start, end }); } } else // if there are planes defined { if (curve.IsLinear(Tolerance)) { if (planes.Length == 1) { glulam = new StraightGlulam(curve, planes); } else { glulam = new StraightGlulam(curve, planes, true); // glulam = new StraightGlulamWithTwist(curve, planes); Console.WriteLine("Not implemented..."); } } else if (curve.IsPlanar(Tolerance)) { Plane crv_plane; curve.TryGetPlane(out crv_plane); /* * Are all the planes perpendicular to the curve normal? * Yes: basic SC Glulam * Are all the planes consistently aligned from the curve normal? * Yes: SC Glulam with rotated cross-section * SC Glulam with twisting */ bool HasTwist = false; foreach (Plane p in planes) { if (Math.Abs(p.XAxis * crv_plane.ZAxis) > Tolerance) { HasTwist = true; } } if (HasTwist) { glulam = new DoubleCurvedGlulam(curve, planes); } else { Plane first = new Plane(curve.PointAtStart, crv_plane.ZAxis, Vector3d.CrossProduct(curve.TangentAtStart, crv_plane.ZAxis)); Plane last = new Plane(curve.PointAtEnd, crv_plane.ZAxis, Vector3d.CrossProduct(curve.TangentAtEnd, crv_plane.ZAxis)); glulam = new SingleCurvedGlulam(curve, new Plane[] { first, last }); } } else { Plane temp; double t; bool Twisted = false; curve.PerpendicularFrameAt(curve.Domain.Min, out temp); double Angle = Vector3d.VectorAngle(planes[0].YAxis, temp.YAxis); for (int i = 0; i < planes.Length; ++i) { curve.ClosestPoint(planes[i].Origin, out t); curve.PerpendicularFrameAt(t, out temp); if (Math.Abs(Vector3d.VectorAngle(planes[0].YAxis, temp.YAxis) - Angle) > AngleTolerance) { // Twisting Glulam Twisted = true; break; } } /* * Are all the planes consistently aligned from some plane? * Yes: DC Glulam with constant cross-section * Are all the planes at a consistent angle from the perpendicular frame of the curve? * Yes: DC Glulam with minimal twisting * DC Glulam with twisting */ if (Twisted) { // TODO: differentiate between DC Glulam with minimal twist, and DC Glulam with twist glulam = new DoubleCurvedGlulam(curve, planes); } else { glulam = new DoubleCurvedGlulam(curve, planes); } } } //glulam.ValidateFrames(); int nh = data.NumHeight; int nw = data.NumWidth; if (glulam is DoubleCurvedGlulam) { if (data.NumHeight < 2) { nh = 2; data.LamHeight /= 2; } if (data.NumWidth < 2) { nw = 2; data.LamWidth /= 2; } data.Lamellae.ResizeArray(nw, nh); } else if (glulam is SingleCurvedGlulam) { if (data.NumHeight < 2) { nh = 2; data.LamHeight /= 2; } data.Lamellae.ResizeArray(nw, nh); } glulam.Data = data; return(glulam); }
/// <summary> /// Create a Glulam from arbitrary geometry and a guide curve. The curve describes the fibre direction of the Glulam. This will /// create a Glulam which completely envelops the input geometry and whose centreline is offset from the input guide curve, to /// preserve the desired fibre orientation. /// </summary> /// <param name="curve">Guide curve to direct the Glulam.</param> /// <param name="beam">Beam geometry as Mesh.</param> /// <param name="extra">Extra material tolerance to leave on Glulam (the width and height of the Glulam will be /// increased by this much).</param> /// <returns>A new Glulam which envelops the input beam geometry, plus an extra tolerance as defined above.</returns> static public Glulam CreateGlulamFromBeamGeometry(Curve curve, Mesh beam, out double true_width, out double true_height, out double true_length, double extra = 0.0) { double t, l; Plane cp = Plane.Unset; Plane cpp; Polyline ch; Mesh m = new Mesh(); List <Plane> frames = new List <Plane>(); double[] tt = curve.DivideByCount(20, true); if (curve.IsLinear()) { m = beam.DuplicateMesh(); curve.PerpendicularFrameAt(curve.Domain.Min, out cp); m.Transform(Rhino.Geometry.Transform.PlaneToPlane(cp, Plane.WorldXY)); m.Faces.Clear(); Plane twist = Plane.WorldXY; m = m.FitToAxes(Plane.WorldXY, out ch, ref twist); double angle = Vector3d.VectorAngle(Vector3d.XAxis, twist.XAxis); int sign = Math.Sign(twist.YAxis * Vector3d.XAxis); cp.Transform(Rhino.Geometry.Transform.Rotation(angle * sign, cp.ZAxis, cp.Origin)); frames.Add(cp); } else if (curve.TryGetPlane(out cpp, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance)) { for (int i = 0; i < tt.Length; ++i) { Vector3d xaxis = Vector3d.CrossProduct(cpp.ZAxis, curve.TangentAt(tt[i])); cp = new Plane(curve.PointAt(tt[i]), xaxis, cpp.ZAxis); frames.Add(cp); } for (int i = 0; i < beam.Vertices.Count; ++i) { Point3d p = new Point3d(beam.Vertices[i]); curve.ClosestPoint(p, out t); l = curve.GetLength(new Interval(curve.Domain.Min, t)); Vector3d xaxis = Vector3d.CrossProduct(cpp.ZAxis, curve.TangentAt(t)); cp = new Plane(curve.PointAt(t), xaxis, cpp.ZAxis); p.Transform(Rhino.Geometry.Transform.PlaneToPlane(cp, Plane.WorldXY)); p.Z = l; m.Vertices.Add(p); } } else { for (int i = 0; i < beam.Vertices.Count; ++i) { Point3d p = new Point3d(beam.Vertices[i]); curve.ClosestPoint(p, out t); l = curve.GetLength(new Interval(curve.Domain.Min, t)); curve.PerpendicularFrameAt(t, out cp); p.Transform(Rhino.Geometry.Transform.PlaneToPlane(cp, Plane.WorldXY)); p.Z = l; m.Vertices.Add(p); } Plane twist = Plane.WorldXY; m = m.FitToAxes(Plane.WorldXY, out ch, ref twist); double angle = Vector3d.VectorAngle(Vector3d.XAxis, twist.XAxis); int sign = Math.Sign(twist.YAxis * Vector3d.XAxis); for (int i = 0; i < tt.Length; ++i) { curve.PerpendicularFrameAt(tt[i], out cp); cp.Transform(Rhino.Geometry.Transform.Rotation(angle * sign, cp.ZAxis, cp.Origin)); frames.Add(cp); } } m.Faces.AddFaces(beam.Faces); m.FaceNormals.ComputeFaceNormals(); BoundingBox bb = m.GetBoundingBox(true); double offsetX = bb.Center.X; double offsetY = bb.Center.Y; Brep bb2 = bb.ToBrep(); bb2.Transform(Rhino.Geometry.Transform.PlaneToPlane(Plane.WorldXY, cp)); true_width = bb.Max.X - bb.Min.X + extra; true_height = bb.Max.Y - bb.Min.Y + extra; // Now we create the glulam... //tasTools.Lam.Glulam glulam = tasTools.Lam.Glulam.CreateGlulam(curve, frames.ToArray()); Beam temp_beam = new Beam(curve, null, frames.ToArray()); int samples = (int)(curve.GetLength() / GlulamData.DefaultSampleDistance); Curve new_curve = temp_beam.CreateOffsetCurve(offsetX, offsetY, samples, true); new_curve = new_curve.Extend(CurveEnd.Both, 5.0 + extra, CurveExtensionStyle.Smooth); GlulamData data = GlulamData.FromCurveLimits(new_curve, frames.ToArray()); if (new_curve.IsPlanar()) { data.LamHeight = Math.Ceiling(true_height); data.Lamellae = new Stick[(int)(Math.Ceiling(true_width / data.LamWidth)), 1]; } else if (new_curve.IsLinear()) { data.LamHeight = Math.Ceiling(true_height); data.LamWidth = Math.Ceiling(true_width); data.Lamellae = new Stick[1, 1]; } else { data.Lamellae = new Stick[(int)(Math.Ceiling(true_width / data.LamWidth)), (int)(Math.Ceiling(true_height / data.LamHeight))]; } Glulam glulam = tas.Lam.Glulam.CreateGlulam(new_curve, frames.ToArray(), data); /* * tt = glulam.Centreline.DivideByCount(100, true); * double maxK = 0.0; * * int index = 0; * Vector3d kvec = Vector3d.Unset; * Vector3d temp; * * for (int i = 0; i < tt.Length; ++i) * { * temp = glulam.Centreline.CurvatureAt(tt[i]); * if (temp.Length > maxK) * { * index = i; * kvec = temp; * maxK = temp.Length; * } * } * Plane frame = glulam.GetPlane(tt[index]); * * double min_lam_width = 1.0; * double min_lam_height = 1.0; * double max_lam_width = (double)((int)Math.Ceiling(true_width / 10.0) * 10.0); * double max_lam_height = (double)((int)Math.Ceiling(true_height / 10.0) * 10.0); * * double lam_width = Math.Ceiling(Math.Min(1 / (Math.Abs(kvec * frame.XAxis) * 200), max_lam_width)); * double lam_height = Math.Ceiling(Math.Min(1 / (Math.Abs(kvec * frame.YAxis) * 200), max_lam_height)); * * if (lam_width == 0.0) lam_width = max_lam_width; * if (lam_height == 0.0) lam_height = max_lam_height; * * glulam.Data.LamHeight = lam_height; * glulam.Data.LamWidth = lam_width; * glulam.Data.NumHeight = (int)(Math.Ceiling(true_height / lam_height)); * glulam.Data.NumWidth = (int)(Math.Ceiling(true_width / lam_width)); * * //double new_lam_height, new_lam_width; * * if (glulam.Data.NumHeight * glulam.Data.LamHeight - true_height > 20.0) * glulam.Data.LamHeight = Math.Ceiling((true_height + 10.0) / glulam.Data.NumHeight); * if (glulam.Data.NumWidth * glulam.Data.LamWidth - true_width > 20.0) * glulam.Data.LamWidth = Math.Ceiling((true_width + 10.0) / glulam.Data.NumWidth); */ true_length = new_curve.GetLength(); return(glulam); }