예제 #1
0
        /// <summary>
        /// Reverse direction of glulam.
        /// </summary>
        public void Reverse()
        {
            Curve Reversed = Centreline.DuplicateCurve();

            Reversed.Reverse();

            Orientation.Remap(Centreline, Reversed);
            Centreline = Reversed;
        }
예제 #2
0
        public override Curve CreateOffsetCurve(double x, double y, bool rebuild = false, int rebuild_pts = 20)
        {
            Vector3d v = Orientation.GetOrientation(Centreline, Centreline.Domain.Min);

            Plane p    = tas.Core.Util.Misc.PlaneFromNormalAndYAxis(Centreline.PointAtStart, Centreline.TangentAtStart, v);
            Curve copy = Centreline.DuplicateCurve();

            copy.Transform(Rhino.Geometry.Transform.Translation(p.XAxis * x + p.YAxis * y));
            return(copy);
        }
예제 #3
0
        public override Curve CreateOffsetCurve(double x, double y, bool offset_start, bool offset_end, bool rebuild = false, int rebuild_pts = 20)
        {
            if (!offset_start && !offset_end)
            {
                return(Centreline.DuplicateCurve());
            }
            if (offset_start && offset_end)
            {
                return(CreateOffsetCurve(x, y, rebuild, rebuild_pts));
            }

            List <Point3d> pts = new List <Point3d>();

            double[] t = Centreline.DivideByCount(this.Data.Samples, true);

            double tmin = offset_start ? t.First() : t.Last();
            double tmax = offset_end ? t.Last() : t.First();

            for (int i = 0; i < t.Length; ++i)
            {
                Plane  p = GetPlane(t[i]);
                double l = Ease.QuadOut(Interpolation.Unlerp(tmin, tmax, t[i]));
                pts.Add(p.Origin + p.XAxis * l * x + p.YAxis * l * y);
            }

            Curve new_curve = Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Uniform,
                                                            Centreline.TangentAtStart, Centreline.TangentAtEnd);

            if (new_curve == null)
            {
                throw new Exception(this.ToString() + "::CreateOffsetCurve:: Failed to create interpolated curve!");
            }

            double len = new_curve.GetLength();

            new_curve.Domain = new Interval(0.0, len);

            if (rebuild)
            {
                new_curve = new_curve.Rebuild(rebuild_pts, new_curve.Degree, true);
            }

            return(new_curve);
        }
예제 #4
0
        public override Glulam Overbend(double t)
        {
            PolyCurve pc = Centreline.DuplicateCurve() as PolyCurve;

            if (pc == null)
            {
                return(this);
            }

            // fix this domain issue... not working for some reason
            PolyCurve pco = pc.OverBend(t);

            pco.Domain = pc.Domain;

            FreeformGlulam g = this.Duplicate() as FreeformGlulam;

            g.Centreline = pco;

            return(g);
        }
예제 #5
0
 /// <summary>
 /// Duplicate glulam data.
 /// </summary>
 /// <returns></returns>
 public Glulam Duplicate() => CreateGlulam(Centreline.DuplicateCurve(), Orientation.Duplicate(), Data.Duplicate());
예제 #6
0
        /// <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;
             * }
             */
        }
예제 #7
0
        public Brep GetSideSurface(int side, double offset, double width, double extension = 0.0, bool flip = false)
        {
            // TODO: Create access for Glulam ends, with offset (either straight or along Centreline).

            side = side.Modulus(2);
            double w2 = width / 2;

            Curve c = Centreline.DuplicateCurve();

            if (extension > 0.0)
            {
                c = c.Extend(CurveEnd.Both, extension, CurveExtensionStyle.Smooth);
            }

            int N = Math.Max(6, Data.Samples);

            GenerateCrossSectionPlanes(N, out Plane[] planes, out double[] parameters, Data.InterpolationType);

            Curve[] rules = new Curve[planes.Length];

            double offsetX, offsetY;

            GetSectionOffset(out offsetX, out offsetY);

            for (int i = 0; i < planes.Length; ++i)
            {
                Plane p = planes[i];
                if (side == 0)
                {
                    rules[i] = new Line(
                        p.Origin + p.XAxis * (offset + offsetX) + p.YAxis * (w2 + offsetY),
                        p.Origin + p.XAxis * (offset + offsetX) - p.YAxis * (w2 - offsetY)
                        ).ToNurbsCurve();
                }
                else
                {
                    rules[i] = new Line(
                        p.Origin + p.YAxis * (offset + offsetY) + p.XAxis * (w2 + offsetX),
                        p.Origin + p.YAxis * (offset + offsetY) - p.XAxis * (w2 - offsetX)
                        ).ToNurbsCurve();
                }
            }

            Brep[] loft = Brep.CreateFromLoft(rules, Point3d.Unset, Point3d.Unset, LoftType.Normal, false);
            if (loft == null || loft.Length < 1)
            {
                throw new Exception("Glulam::GetSideSurface::Loft failed!");
            }

            Brep brep = loft[0];

            Point3d  pt  = brep.Faces[0].PointAt(brep.Faces[0].Domain(0).Mid, brep.Faces[0].Domain(1).Mid);
            Vector3d nor = brep.Faces[0].NormalAt(brep.Faces[0].Domain(0).Mid, brep.Faces[0].Domain(1).Mid);

            double ct;

            Centreline.ClosestPoint(pt, out ct);
            Vector3d nor2 = Centreline.PointAt(ct) - pt;

            nor2.Unitize();

            if (nor2 * nor < 0.0)
            {
                brep.Flip();
            }

            if (flip)
            {
                brep.Flip();
            }

            return(brep);
        }
예제 #8
0
        /// <summary>
        /// Map points from beam space to world space.
        /// </summary>
        /// <param name="pts"></param>
        /// <returns></returns>
        public Point3d[] FromBeamSpace(IList <Point3d> pts, bool extend = true)
        {
            Point3d[] m_output_pts = new Point3d[pts.Count];

            var    curve  = Centreline.DuplicateCurve();
            double length = curve.GetLength();

            if (extend)
            {
                double maxZ = 0;
                foreach (Point3d pt in pts)
                {
                    maxZ = Math.Max(maxZ, pt.Z);
                }

                if (maxZ > length)
                {
                    curve = curve.Extend(CurveEnd.End, maxZ - length + 1, CurveExtensionStyle.Line);
                }
            }

            /*
             * double min_z = double.MaxValue;
             * double max_z = double.MinValue;
             *
             * foreach (var pt in pts)
             * {
             *  min_z = Math.Min(min_z, pt.Z);
             *  max_z = Math.Max(max_z, pt.Z);
             * }
             *
             * double ext_min = Math.Min(0, Centreline.Domain.Min - min_z);
             * double ext_max = Math.Max(0, max_z - Centreline.Domain.Max);
             * double tolerance = 5.0;
             *
             * double ext = Math.Max(ext_min, ext_max) + tolerance;
             *
             * Curve c = Centreline.Extend(CurveEnd.Both, ext, CurveExtensionStyle.Line);
             */

            if (curve.IsLinear())
            {
                curve.Domain = new Interval(0, length);

                Parallel.For(0, pts.Count, i =>
                {
                    Plane m_plane;

                    //m_plane = Utility.PlaneFromNormalAndYAxis(
                    //Centreline.PointAtStart + Centreline.TangentAtStart * (pts[i].Z),
                    //Centreline.TangentAtStart,
                    //Orientation.GetOrientation(Centreline, pts[i].Z));

                    m_plane = GetPlane(pts[i].Z, curve);

                    m_output_pts[i] = m_plane.PointAt(pts[i].X, pts[i].Y);
                });
            }

            else
            {
                //Parallel.For(0, pts.Count, i =>
                //{
                for (int i = 0; i < pts.Count; ++i)
                {
                    Plane m_plane;

                    curve.LengthParameter(pts[i].Z, out double t);
                    m_plane = GetPlane(t, curve);

                    m_output_pts[i] = m_plane.PointAt(pts[i].X, pts[i].Y);
                }
                //});
            }

            return(m_output_pts);
        }