public StraightGlulam(Curve curve, GlulamOrientation orientation, GlulamData data) : base() { Data = data.Duplicate(); Orientation = orientation; Centreline = curve.DuplicateCurve(); //Centreline.Domain.MakeIncreasing(); }
public Glulam Generate() { GlulamData data = new GlulamData(Centreline, Width, Height, Frames.ToArray(), CrossSectionSamples, 100); Glulam g = Glulam.CreateGlulam(Centreline, Frames.ToArray(), data); return(g); }
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)); }
public GlulamData Duplicate() { GlulamData data = new GlulamData(); data.LamHeight = LamHeight; data.LamWidth = LamWidth; data.Samples = Samples; data.SectionAlignment = SectionAlignment; data.InterpolationType = InterpolationType; data.Lamellae = new Stick[NumWidth, NumHeight]; Array.Copy(Lamellae, data.Lamellae, Lamellae.Length); return(data); }
public Glulam Trim(Interval domain, double overlap) { double l1 = Centreline.GetLength(new Interval(Centreline.Domain.Min, domain.Min)); double l2 = Centreline.GetLength(new Interval(Centreline.Domain.Min, domain.Max)); double t1, t2; if (!Centreline.LengthParameter(l1 - overlap, out t1)) { t1 = domain.Min; } if (!Centreline.LengthParameter(l2 + overlap, out t2)) { t2 = domain.Max; } domain = new Interval( Math.Max(t1, Centreline.Domain.Min), Math.Min(t2, Centreline.Domain.Max)); double length = Centreline.GetLength(domain); if (domain.IsDecreasing || length < overlap || length < Glulam.OverlapTolerance) { return(null); } double percentage = length / Centreline.GetLength(); GlulamData data = Data.Duplicate(); data.Samples = Math.Max(6, (int)(data.Samples * percentage)); Curve trimmed_curve = Centreline.Trim(domain); GlulamOrientation trimmed_orientation = Orientation.Trim(domain); trimmed_orientation.Remap(Centreline, trimmed_curve); Glulam glulam = CreateGlulam(trimmed_curve, trimmed_orientation, data); return(glulam); }
public GlulamData(Curve c, double width, double height, Plane[] frames = null, int glulam_samples = 50, int curve_samples = 0) { double lw, lh; GlulamData.GetLamellaSizes(c, out lw, out lh, frames, curve_samples); lw = Math.Min(lw, width); lh = Math.Min(lh, height); int num_width = (int)Math.Ceiling(width / lw); int num_height = (int)Math.Ceiling(height / lh); Lamellae = new Stick[num_width, num_height]; LamWidth = width / num_width; LamHeight = height / num_height; Samples = glulam_samples; }
public static GlulamData FromByteArray(byte[] b) { if (b.Length != 28) { throw new Exception("Byte array is wrong size for GlulamData!"); } GlulamData data = new GlulamData(); int num_height = BitConverter.ToInt32(b, 0); int num_width = BitConverter.ToInt32(b, 4); data.LamHeight = BitConverter.ToDouble(b, 8); data.LamWidth = BitConverter.ToDouble(b, 16); data.Samples = BitConverter.ToInt32(b, 24); data.SectionAlignment = (GlulamData.CrossSectionPosition)BitConverter.ToInt32(b, 32); data.InterpolationType = (GlulamData.Interpolation)BitConverter.ToInt32(b, 40); data.Lamellae = new Stick[num_width, num_height]; return(data); }
/// <summary> /// Split glulam into two at parameter t. /// </summary> /// <param name="t">Curve parameter to split glulam at.</param> /// <returns>List of new glulams.</returns> public List <Glulam> Split(double t) { if (!Centreline.Domain.IncludesParameter(t)) { return(null); } double percentage = (t - Centreline.Domain.Min) / (Centreline.Domain.Max - Centreline.Domain.Min); Plane split_plane = GetPlane(t); Curve[] split_curves = Centreline.Split(t); if (split_curves == null || split_curves.Length != 2) { return(null); } GlulamData Data1 = Data.Duplicate(); Data1.Samples = (int)(Data.Samples * percentage); GlulamOrientation[] SplitOrientations = Orientation.Split(new double[] { t }); Glulam Blank1 = CreateGlulam(split_curves[0], SplitOrientations[0], Data1); GlulamData Data2 = Data.Duplicate(); Data2.Samples = (int)(Data.Samples * (1 - percentage)); Glulam Blank2 = CreateGlulam(split_curves[1], SplitOrientations[1], Data2); List <Glulam> blanks = new List <Glulam>() { Blank1, Blank2 }; return(blanks); }
/// <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); }
static public Glulam CreateGlulam(Curve curve, GlulamOrientation orientation, GlulamData data) { Glulam glulam; if (curve.IsLinear(Tolerance)) { glulam = new StraightGlulam(curve, orientation, data); } else if (curve.IsPlanar(Tolerance)) { /* * if (data.NumHeight < 2) * { * data.Lamellae.ResizeArray(data.NumWidth, 2); * data.LamHeight /= 2; * } */ glulam = new SingleCurvedGlulam(curve, orientation, data); } else { /* * if (data.NumHeight < 2) * { * data.Lamellae.ResizeArray(data.NumWidth, 2); * data.LamHeight /= 2; * } * * if (data.NumWidth < 2) * { * data.Lamellae.ResizeArray(2, data.NumHeight); * data.LamWidth /= 2; * } */ glulam = new DoubleCurvedGlulam(curve, orientation, 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); }
/// <summary> /// Create glulam with frames that are aligned with a Surface. The input curve does not /// necessarily have to lie on the Surface. /// </summary> /// <param name="curve">Input centreline of the Glulam.</param> /// <param name="srf">Surface to align the Glulam orientation to.</param> /// <param name="num_samples">Number of orientation frames to use for alignment.</param> /// <returns>New Glulam oriented to the Surface.</returns> static public Glulam CreateGlulamNormalToSurface_old(Curve curve, Brep brep, int num_samples = 20, GlulamData data = null) { double[] t = curve.DivideByCount(num_samples, true); List <Plane> planes = new List <Plane>(); double u, v; Vector3d xaxis, yaxis, zaxis; ComponentIndex ci; Point3d pt; for (int i = 0; i < t.Length; ++i) { brep.ClosestPoint(curve.PointAt(t[i]), out pt, out ci, out u, out v, 0, out yaxis); zaxis = curve.TangentAt(t[i]); xaxis = Vector3d.CrossProduct(zaxis, yaxis); planes.Add(new Plane(curve.PointAt(t[i]), xaxis, yaxis)); } return(Glulam.CreateGlulam(curve, planes.ToArray(), data)); }
/// <summary> /// Create glulam with frames that are aligned with a Brep. The input curve does not /// necessarily have to lie on the Brep. /// </summary> /// <param name="curve">Input centreline of the glulam.</param> /// <param name="brep">Brep to align the glulam orientation to.</param> /// <param name="num_samples">Number of orientation frames to use for alignment.</param> /// <returns>New Glulam oriented to the brep.</returns> static public Glulam CreateGlulamNormalToSurface(Curve curve, Brep brep, int num_samples = 20, GlulamData data = null) { Plane[] frames = tas.Core.Util.Misc.FramesNormalToSurface(curve, brep, num_samples); return(Glulam.CreateGlulam(curve, frames, data)); }
public static GlulamData FromCurveLimits(Curve c, double width, double height, Plane[] frames = null) { Beam beam = new Lam.Beam(c, null, frames); double[] tt = beam.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 = beam.Centreline.CurvatureAt(tt[i]); if (temp.Length > maxK) { index = i; kvec = temp; maxK = temp.Length; } } Plane frame = beam.GetPlane(tt[index]); if (frame == null) { throw new Exception("Frame is null!"); } //double max_lam_width = Math.Ceiling(width); //double max_lam_height = Math.Ceiling(height); double max_lam_width = width; double max_lam_height = height; //double lam_width = Math.Ceiling(Math.Min(1 / (Math.Abs(kvec * frame.XAxis) * Glulam.RadiusMultiplier), max_lam_width)); //double lam_height = Math.Ceiling(Math.Min(1 / (Math.Abs(kvec * frame.YAxis) * Glulam.RadiusMultiplier), max_lam_height)); double lam_width = Math.Min(1 / (Math.Abs(kvec * frame.XAxis) * Glulam.RadiusMultiplier), max_lam_width); double lam_height = Math.Min(1 / (Math.Abs(kvec * frame.YAxis) * Glulam.RadiusMultiplier), max_lam_height); if (lam_width == 0.0) { lam_width = max_lam_width; } if (lam_height == 0.0) { lam_height = max_lam_height; } GlulamData data = new GlulamData(); data.LamHeight = lam_height; data.LamWidth = lam_width; int num_height = (int)(Math.Ceiling(height / lam_height)); int num_width = (int)(Math.Ceiling(width / lam_width)); data.Lamellae = new Stick[num_width, num_height]; data.Samples = (int)(c.GetLength() / DefaultSampleDistance); // I forget why this is here... if (data.NumHeight * data.LamHeight - height > 20.0) { data.LamHeight = Math.Ceiling((height + 10.0) / data.NumHeight); } if (data.NumWidth * data.LamWidth - width > 20.0) { data.LamWidth = Math.Ceiling((width + 10.0) / data.NumWidth); } return(data); }