Пример #1
0
 public StraightGlulam(Curve curve, GlulamOrientation orientation, GlulamData data) : base()
 {
     Data        = data.Duplicate();
     Orientation = orientation;
     Centreline  = curve.DuplicateCurve();
     //Centreline.Domain.MakeIncreasing();
 }
Пример #2
0
        public Glulam Generate()
        {
            GlulamData data = new GlulamData(Centreline, Width, Height, Frames.ToArray(), CrossSectionSamples, 100);
            Glulam     g    = Glulam.CreateGlulam(Centreline, Frames.ToArray(), data);

            return(g);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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;
        }
Пример #7
0
        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);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        /// <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);
        }
Пример #12
0
        /// <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));
        }
Пример #13
0
 /// <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));
 }
Пример #14
0
        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);
        }