public override Mesh GetBoundingMesh(double offset = 0.0, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { //Curve CL = Centreline.Extend(CurveEnd.Both, offset, CurveExtensionStyle.Line); Mesh m = new Mesh(); double[] parameters; Plane[] frames; int N = 2; GenerateCrossSectionPlanes(N, out frames, out parameters, interpolation); double hW = Data.NumWidth * Data.LamWidth / 2 + offset; double hH = Data.NumHeight * Data.LamHeight / 2 + offset; Plane pplane; // vertex index and next frame vertex index int i4; int ii4; double Length = Centreline.GetLength() + offset * 2; double MaxT = parameters.Last() - parameters.First(); double Width = Data.NumWidth * Data.LamWidth / 1000; double Height = Data.NumHeight * Data.LamHeight / 1000; for (int i = 0; i < parameters.Length; ++i) { i4 = i * 8; ii4 = i4 - 8; pplane = frames[i]; for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Point3d v = pplane.Origin + hW * j * pplane.XAxis + hH * k * pplane.YAxis; m.Vertices.Add(v); m.Vertices.Add(v); } } //double DivV = DivParams[i] / MaxT; double DivV = parameters[i] / MaxT * Length / 1000; m.TextureCoordinates.Add(2 * Width + 2 * Height, DivV); m.TextureCoordinates.Add(0.0, DivV); m.TextureCoordinates.Add(Height, DivV); m.TextureCoordinates.Add(Height, DivV); m.TextureCoordinates.Add(2 * Height + Width, DivV); m.TextureCoordinates.Add(2 * Height + Width, DivV); m.TextureCoordinates.Add(Width + Height, DivV); m.TextureCoordinates.Add(Width + Height, DivV); if (i > 0) { m.Faces.AddFace(i4 + 2, ii4 + 2, ii4 + 1, i4 + 1); m.Faces.AddFace(i4 + 6, ii4 + 6, ii4 + 3, i4 + 3); m.Faces.AddFace(i4 + 4, ii4 + 4, ii4 + 7, i4 + 7); m.Faces.AddFace(i4, ii4, ii4 + 5, i4 + 5); } } // Start cap pplane = GetPlane(parameters.First()); Point3d vc = pplane.Origin + hW * -1 * pplane.XAxis + hH * -1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * -1 * pplane.XAxis + hH * 1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * 1 * pplane.XAxis + hH * -1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * 1 * pplane.XAxis + hH * 1 * pplane.YAxis; m.Vertices.Add(vc); m.TextureCoordinates.Add(0, 0); m.TextureCoordinates.Add(0, Height); m.TextureCoordinates.Add(Width, 0); m.TextureCoordinates.Add(Width, Height); m.Faces.AddFace(m.Vertices.Count - 4, m.Vertices.Count - 3, m.Vertices.Count - 1, m.Vertices.Count - 2); // End cap pplane = GetPlane(parameters.Last()); vc = pplane.Origin + hW * -1 * pplane.XAxis + hH * -1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * -1 * pplane.XAxis + hH * 1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * 1 * pplane.XAxis + hH * -1 * pplane.YAxis; m.Vertices.Add(vc); vc = pplane.Origin + hW * 1 * pplane.XAxis + hH * 1 * pplane.YAxis; m.Vertices.Add(vc); m.TextureCoordinates.Add(0, 0); m.TextureCoordinates.Add(0, Height); m.TextureCoordinates.Add(Width, 0); m.TextureCoordinates.Add(Width, Height); m.Faces.AddFace(m.Vertices.Count - 2, m.Vertices.Count - 1, m.Vertices.Count - 3, m.Vertices.Count - 4); m.Vertices.CullUnused(); m.Compact(); //m.UserDictionary.ReplaceContentsWith(GetArchivableDictionary()); //m.UserDictionary.Set("glulam", GetArchivableDictionary()); return(m); }
public override void GenerateCrossSectionPlanes(int N, out Plane[] planes, out double[] t, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { //Curve CL = Centreline.Extend(CurveEnd.Both, offset, CurveExtensionStyle.Line); Curve CL = Centreline; t = new double[] { CL.Domain.Min, CL.Domain.Max }; Array.Sort(t); planes = new Plane[] { GetPlane(t[0]), GetPlane(t[1]) }; }
public virtual Mesh ToMesh(double offset = 0.0, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { return(new Mesh()); }
public abstract void GenerateCrossSectionPlanes(int N, out Plane[] planes, out double[] t, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR);
/// <summary> /// Generate a series of planes on the glulam cross-section. TODO: Re-implement as GlulamOrientation function /// </summary> /// <param name="N">Number of planes to extract.</param> /// <param name="extension">Extension of the centreline curve</param> /// <param name="frames">Output cross-section planes.</param> /// <param name="parameters">Output t-values along centreline curve.</param> /// <param name="interpolation">Type of interpolation to use (default is Linear).</param> public override void GenerateCrossSectionPlanes(int N, out Plane[] frames, out double[] parameters, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { Curve curve = Centreline; double multiplier = RhinoMath.UnitScale(Rhino.RhinoDoc.ActiveDoc.ModelUnitSystem, UnitSystem.Millimeters); //PolylineCurve discrete = curve.ToPolyline(Glulam.Tolerance * 10, Glulam.AngleTolerance, 0.0, 0.0); PolylineCurve discrete = curve.ToPolyline(multiplier * Tolerance, AngleTolerance, multiplier * MininumSegmentLength, curve.GetLength() / MinimumNumSegments); if (discrete.TryGetPolyline(out Polyline discrete2)) { N = discrete2.Count; parameters = new double[N]; for (int i = 0; i < N; ++i) { curve.ClosestPoint(discrete2[i], out parameters[i]); } } else { parameters = curve.DivideByCount(N - 1, true).ToArray(); } //frames = parameters.Select(x => GetPlane(x)).ToArray(); //return; frames = new Plane[parameters.Length]; var vectors = Orientation.GetOrientations(curve, parameters); Plane temp; for (int i = 0; i < parameters.Length; ++i) { temp = Misc.PlaneFromNormalAndYAxis( curve.PointAt(parameters[i]), curve.TangentAt(parameters[i]), vectors[i]); if (temp.IsValid) { frames[i] = temp; } else { throw new Exception(string.Format("Plane is invalid: vector {0} tangent {1}", vectors[i], curve.TangentAt(parameters[i]))); } // TODO: Make back-up orientation direction in this case. } return; N = Math.Max(N, 2); frames = new Plane[N]; Curve CL; double extension = 0; if (Centreline.IsClosed) { CL = Centreline.DuplicateCurve(); } else { CL = Centreline.Extend(CurveEnd.Both, extension, CurveExtensionStyle.Smooth); } parameters = CL.DivideByCount(N - 1, true); GlulamOrientation TempOrientation = Orientation.Duplicate(); TempOrientation.Remap(Centreline, CL); for (int i = 0; i < N; ++i) { Vector3d v = TempOrientation.GetOrientation(CL, parameters[i]); frames[i] = tas.Core.Util.Misc.PlaneFromNormalAndYAxis(CL.PointAt(parameters[i]), CL.TangentAt(parameters[i]), v); } return; /* * double[] ft = new double[Frames.Count]; * double[] fa = new double[Frames.Count]; * * Plane temp; * for (int i = 0; i < Frames.Count; ++i) * { * CL.PerpendicularFrameAt(Frames[i].Item1, out temp); * ft[i] = Frames[i].Item1; * //fa[i] = Math.Acos(temp.YAxis * Frames[i].Item2.YAxis); * fa[i] = Vector3d.VectorAngle(temp.YAxis, Frames[i].Item2.YAxis, Frames[i].Item2); * } * * for (int i = 1; i < fa.Length; ++i) * { * if (fa[i] - fa[i - 1] > Math.PI) * fa[i] -= Constants.Tau; * else if (fa[i] - fa[i - 1] < -Math.PI) * fa[i] += Constants.Tau; * } * * int res; * int max = ft.Length - 1; * double mu; * * double[] angles = new double[N]; * * if (Frames.Count < 3) * interpolation = GlulamData.Interpolation.LINEAR; * * switch (interpolation) * { * case (GlulamData.Interpolation.HERMITE): // Hermite Interpolation * for (int i = 0; i < N; ++i) * { * if (t[i] < ft[0]) * { * angles[i] = fa[0]; * continue; * } * else if (t[i] > ft.Last()) * { * angles[i] = fa.Last(); * continue; * } * * res = Array.BinarySearch(ft, t[i]); * if (res < 0) * { * res = ~res; * res--; * } * * if (res == 0 && res < max - 1) * { * mu = (t[i] - ft[0]) / (ft[1] - ft[0]); * angles[i] = Interpolation.HermiteInterpolate(fa[0], fa[0], fa[1], fa[2], mu, 0, 0); * } * else if (res > 0 && res < max - 1) * { * mu = (t[i] - ft[res]) / (ft[res + 1] - ft[res]); * angles[i] = Interpolation.HermiteInterpolate(fa[res - 1], fa[res], fa[res + 1], fa[res + 2], mu, 0, 0); * * } * else if (res > 0 && res < max) * { * mu = (t[i] - ft[res]) / (ft[res + 1] - ft[res]); * angles[i] = Interpolation.HermiteInterpolate(fa[res - 1], fa[res], fa[res + 1], fa[res + 1], mu, 0, 0); * } * else if (res == max) * { * angles[i] = fa[res]; * } * * else * continue; * } * break; * * case (GlulamData.Interpolation.CUBIC): // Cubic Interpolation * for (int i = 0; i < N; ++i) * { * if (t[i] <= ft[0]) * { * angles[i] = fa[0]; * continue; * } * else if (t[i] >= ft.Last()) * { * angles[i] = fa.Last(); * continue; * } * * res = Array.BinarySearch(ft, t[i]); * if (res < 0) * { * res = ~res; * res--; * } * * if (res == 0 && res < max - 1) * { * mu = (t[i] - ft[0]) / (ft[1] - ft[0]); * angles[i] = Interpolation.CubicInterpolate(fa[0], fa[0], fa[1], fa[2], mu); * } * else if (res > 0 && res < max - 1) * { * mu = (t[i] - ft[res]) / (ft[res + 1] - ft[res]); * angles[i] = Interpolation.CubicInterpolate(fa[res - 1], fa[res], fa[res + 1], fa[res + 2], mu); * * } * else if (res > 0 && res < max) * { * mu = (t[i] - ft[res]) / (ft[res + 1] - ft[res]); * angles[i] = Interpolation.CubicInterpolate(fa[res - 1], fa[res], fa[res + 1], fa[res + 1], mu); * } * else if (res == max) * { * angles[i] = fa[res]; * } * * else * continue; * } * break; * * default: // Default linear interpolation * for (int i = 0; i < N; ++i) * { * res = Array.BinarySearch(ft, t[i]); * if (res < 0) * { * res = ~res; * res--; * } * if (res >= 0 && res < max) * { * if (ft[res + 1] - ft[res] == 0) * mu = 0.5; * else * mu = Math.Min(1.0, Math.Max(0, (t[i] - ft[res]) / (ft[res + 1] - ft[res]))); * angles[i] = Interpolation.Lerp(fa[res], fa[res + 1], mu); * } * else if (res < 0) * angles[i] = fa[0]; * else if (res >= max) * angles[i] = fa[max]; * } * break; * } * * for (int i = 0; i < N; ++i) * { * CL.PerpendicularFrameAt(t[i], out temp); * temp.Transform(Rhino.Geometry.Transform.Rotation(angles[i], temp.ZAxis, temp.Origin)); * planes[i] = temp; * } */ }
public override Mesh GetBoundingMesh(double offset = 0.0, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { Mesh m = new Mesh(); int N = Math.Max(Data.Samples, 6); GenerateCrossSectionPlanes(N, out Plane[] frames, out double[] parameters, Data.InterpolationType); GetSectionOffset(out double offsetX, out double offsetY); Point3d[] m_corners = GenerateCorners(); double hW = Data.NumWidth * Data.LamWidth / 2 + offset; double hH = Data.NumHeight * Data.LamHeight / 2 + offset; // vertex index and next frame vertex index int i4; int ii4; //double texLength = (Centreline.GetLength() + offset * 2) / 1000; //double MaxT = parameters.Last() - parameters.First(); double texWidth = Width / 1000.0; // Width in meters double texHeight = Height / 1000.0; // Height in meters for (int i = 0; i < frames.Length; ++i) { i4 = i * 8; ii4 = i4 - 8; double texLength = Centreline.GetLength( new Interval(Centreline.Domain.Min, parameters[i])) / 1000; for (int j = 0; j < m_corners.Length; ++j) { Point3d v = frames[i].PointAt(m_corners[j].X, m_corners[j].Y); m.Vertices.Add(v); m.Vertices.Add(v); } //double DivV = parameters[i] / MaxT * Length / 1000; m.TextureCoordinates.Add(texLength, 2 * texWidth + 2 * texHeight); m.TextureCoordinates.Add(texLength, 0.0); m.TextureCoordinates.Add(texLength, texHeight); m.TextureCoordinates.Add(texLength, texHeight); m.TextureCoordinates.Add(texLength, 2 * texHeight + texWidth); m.TextureCoordinates.Add(texLength, 2 * texHeight + texWidth); m.TextureCoordinates.Add(texLength, texWidth + texHeight); m.TextureCoordinates.Add(texLength, texWidth + texHeight); if (i > 0) { m.Faces.AddFace(i4 + 2, ii4 + 2, ii4 + 1, i4 + 1); m.Faces.AddFace(i4 + 5, ii4 + 5, ii4 + 3, i4 + 3); m.Faces.AddFace(i4 + 7, ii4 + 7, ii4 + 4, i4 + 4); m.Faces.AddFace(i4, ii4, ii4 + 7, i4 + 7); } } Plane pplane; // Start cap pplane = frames.First(); //m_section_corners.Select(x => frames.Select(y => m.Vertices.Add(y.PointAt(x.X, x.Y)))); for (int j = 0; j < m_corners.Length; ++j) { m.Vertices.Add(pplane.PointAt(m_corners[j].X, m_corners[j].Y)); } m.TextureCoordinates.Add(0, 0); m.TextureCoordinates.Add(0, texHeight); m.TextureCoordinates.Add(texWidth, 0); m.TextureCoordinates.Add(texWidth, texHeight); m.Faces.AddFace(m.Vertices.Count - 4, m.Vertices.Count - 3, m.Vertices.Count - 2, m.Vertices.Count - 1); // End cap pplane = frames.Last(); for (int j = 0; j < m_corners.Length; ++j) { m.Vertices.Add(pplane.PointAt(m_corners[j].X, m_corners[j].Y)); } m.TextureCoordinates.Add(0, 0); m.TextureCoordinates.Add(0, texHeight); m.TextureCoordinates.Add(texWidth, 0); m.TextureCoordinates.Add(texWidth, texHeight); m.Faces.AddFace(m.Vertices.Count - 1, m.Vertices.Count - 2, m.Vertices.Count - 3, m.Vertices.Count - 4); //m.UserDictionary.ReplaceContentsWith(GetArchivableDictionary()); //m.UserDictionary.Set("glulam", GetArchivableDictionary()); return(m); }
/// <summary> /// Generate a series of planes on the glulam cross-section. TODO: Re-implement as GlulamOrientation function /// </summary> /// <param name="N">Number of planes to extract.</param> /// <param name="extension">Extension of the centreline curve</param> /// <param name="frames">Output cross-section planes.</param> /// <param name="parameters">Output t-values along centreline curve.</param> /// <param name="interpolation">Type of interpolation to use (default is Linear).</param> public override void GenerateCrossSectionPlanes(int N, out Plane[] frames, out double[] parameters, GlulamData.Interpolation interpolation = GlulamData.Interpolation.LINEAR) { Curve curve = Centreline; double multiplier = RhinoMath.UnitScale(UnitSystem.Millimeters, Rhino.RhinoDoc.ActiveDoc.ModelUnitSystem); //PolylineCurve discrete = curve.ToPolyline(Glulam.Tolerance * 10, Glulam.AngleTolerance, 0.0, 0.0); PolylineCurve discrete = curve.ToPolyline(multiplier * Tolerance, AngleTolerance, multiplier * MininumSegmentLength, curve.GetLength() / MinimumNumSegments); if (discrete == null) { parameters = curve.DivideByCount(N - 1, true).ToArray(); //discrete = new PolylineCurve(new Point3d[] { curve.PointAtStart, curve.PointAtEnd }); } else { if (discrete.TryGetPolyline(out Polyline discrete2)) { N = discrete2.Count; parameters = new double[N]; for (int i = 0; i < N; ++i) { curve.ClosestPoint(discrete2[i], out parameters[i]); } } else { parameters = curve.DivideByCount(N - 1, true).ToArray(); } } //frames = parameters.Select(x => GetPlane(x)).ToArray(); //return; frames = new Plane[parameters.Length]; var vectors = Orientation.GetOrientations(curve, parameters); Plane temp; for (int i = 0; i < parameters.Length; ++i) { temp = Utility.PlaneFromNormalAndYAxis( curve.PointAt(parameters[i]), curve.TangentAt(parameters[i]), vectors[i]); if (temp.IsValid) { frames[i] = temp; } else { throw new Exception(string.Format("Plane is invalid: vector {0} tangent {1}", vectors[i], curve.TangentAt(parameters[i]))); } } return; }