Beispiel #1
0
        private double FitCurve()
        {
            if (m_Group == null || m_Group.Count < 5)
                return 0;

            Vect2 uv = new Vect2();
            Vect3 xyz = new Vect3(), xprev = new Vect3();

            List<IFitPoint> fit = new List<IFitPoint>(m_Group.Count);
            //get target point on starting yarn
            //yar0.xVal(m_sPos, ref uv, ref xyz);
            double s1 = m_sPos, d = 0;
            //fit.Add(new FixedPoint(uv));
            double length = 0, h=0;
            Vect2 v;
            List<Vect2> combs = new List<Vect2>(m_Group.Count);
            for (int i = 0; i < m_Group.Count; i++)
            {
                m_Group[i].xVal(s1, ref uv, ref xprev);
                fit.Add(new FixedPoint(uv[0], uv[1]));
                //find closest point on yar1 to the target point on yar0;
                if (i < m_Group.Count - 1)
                {
                    xyz.Set(xprev);
                    //find the spacing to the next yarn
                    if (!CurveTools.xClosest(m_Group[i + 1], ref s1, ref uv, ref xyz, ref d, 1e-6, true))
                        Logger.logger.Instance.Log("xClosest failed in DensityComb");
                        //throw new Exception("xClosest failed in DensityComb");
                    h = xyz.Distance(xprev);
                    //store the spacing and x-distance
                    v = new Vect2();
                    v[0] = length;
                    v[1] = m_Group.InverseSpacing(h);
                    combs.Add(v);

                    length += h;//accumulate length
                }
            }

            Length = length;
            //convert x-distance to s-spacing
            for (int i = 0; i < combs.Count; i++)
                fit[i][0] = combs[i][0] /= length;
            combs.Add(new Vect2(1, m_Group.InverseSpacing(h)));//add endpoint with spacing to previous curve
            //fit to the intersection points
            SurfaceCurve.SimpleFit(this, fit.ToArray());
            FitComb(combs.ToArray());
            return DPI = m_Group.YarnDenier * .0254 * (m_Group.Count - 1) / length;
        }
Beispiel #2
0
        public virtual List<Entity> CreateEntities(bool bFitPoints, double TolAngle, out double[] sPos)
        {
            if (!AllFitPointsValid())
            {
                sPos = null;
                return new List<Entity>();
            }

            List<double> spos = new List<double>();
            const int TEST = 8;
            int FitLength = FitPoints.Length;
            double[] stest = new double[(FitLength - 1) * TEST];
            Vect3[] xtest = new Vect3[(FitLength - 1) * TEST];
            Vect2 uv = new Vect2();
            Vect3 xyz = new Vect3();
            Vect3 dxp = new Vect3(), dxm = new Vect3();
            //initial 8 subdivisions per segment
            int nFit, nTest = 0;
            for (nFit = 1; nFit < FitLength; nFit++)
            {
                for (int i = 0; i < TEST; i++, nTest++)
                {
                    stest[nTest] = BLAS.interpolate(i, TEST, FitPoints[nFit].S, FitPoints[nFit - 1].S);
                    xtest[nTest] = new Vect3();
                    xVal(stest[nTest], ref uv, ref xtest[nTest]);
                }
            }

            //test the midpoint of each subsegment to determine required # of points
            int[] nAdd = new int[stest.Length];
            double cosA;
            double smid;
            int nTotal = FitLength;
            for (nTest = 1; nTest < stest.Length; nTest++)
            {
                //midpoint position
                smid = (stest[nTest] + stest[nTest - 1]) / 2.0;
                xVal(smid, ref uv, ref xyz);
                //forward and backward tangents
                dxp = xtest[nTest] - xyz;
                dxm = xtest[nTest - 1] - xyz;
                //change in angle between for and aft tans
                cosA = -(dxp.Dot(dxm)) / (dxp.Magnitude * dxm.Magnitude);
                Utilities.LimitRange(-1, ref cosA, 1);
                cosA = Math.Acos(cosA);
                //determine additional points and sum total
                nTotal += nAdd[nTest] = (int)(cosA / TolAngle + 1);
            }

            m_Length = 0;
            Vect3 xprev = new Vect3();
            Vect3 dx = new Vect3();
            List<Point3D> pnts = new List<Point3D>();
            List<Vect3> tans = new List<Vect3>();
            xVal(stest[0], ref uv, ref xprev);
            pnts.Add(new Point3D(xprev.ToArray()));
            spos.Add(stest[0]);
            for (nTest = 1; nTest < stest.Length; nTest++)
            {
                for (int i = 1; i <= nAdd[nTest]; i++)
                {
                    smid = ((nAdd[nTest] - i) * stest[nTest - 1] + i * stest[nTest]) / nAdd[nTest];
                    xVec(smid, ref uv, ref xyz, ref dx);
                    spos.Add(smid);
                    pnts.Add(new Point3D(xyz.ToArray()));
                    tans.Add(new Vect3(dx));
                    m_Length += xyz.Distance(xprev);
                    xprev.Set(xyz);
                }
            }

            if (EXTENDENTITY)
            {
                //add for-cast/back-cast points
                for (int i = 0; i < 2; i++)
                {
                    for (nTest = 0; nTest < 10; nTest++)
                    {
                        smid = BLAS.interpolant(nTest, 10) * 0.05;//scale down to .1 cast
                        if (i == 0)
                            smid = -smid;
                        else
                            smid += 1.0;

                        xVal(smid, ref uv, ref xyz);
                        if (i == 0)
                            pnts.Insert(0, new Point3D(xyz.ToArray()));
                        else
                            pnts.Add(new Point3D(xyz.ToArray()));
                    }
                }
            }

            LinearPath lp = new LinearPath(pnts);
            lp.EntityData = this;
            //lp.LineWeight = 3.0f;
            //lp.LineWeightMethod = colorMethodType.byEntity;
            List<Entity> tanpaths = new List<Entity>();
            tanpaths.Add(lp);
            if (bFitPoints)
            {
                //LinearPath path;
                //int npnt = 0;
                //foreach (Vect3 pnt in tans)
                //{
                //	pnt.Magnitude = 2;
                //	xyz = new Vect3(pnts[npnt].ToArray());
                //	xyz += pnt;
                //	path = new LinearPath(pnts[npnt], new Point3D(xyz.ToArray()));
                //	path.EntityData = this;
                //	tanpaths.Add(path);
                //	npnt++;
                //	//xVal(pnt.UV, ref xyz);
                //	//pnts.Add(new Point3D(xyz.ToArray()));
                //}
                pnts = new List<Point3D>();
                foreach (IFitPoint pnt in FitPoints)
                {
                    xVal(pnt.UV, ref xyz);
                    pnts.Add(new Point3D(xyz.ToArray()));
                }
                PointCloud pc = new PointCloud(pnts, 8f);
                pc.EntityData = this;
                tanpaths.Add(pc);
            }
            sPos = spos.ToArray();
            return tanpaths;
        }
Beispiel #3
0
        /// <summary>
        /// fit a curve to the specified points
        /// requires S parameter specified for each point
        /// requires at least 5 points
        /// </summary>
        /// <param name="points">points to fit to, minimum 5</param>
        internal static void SimpleFit(MouldCurve c, IFitPoint[] points)
        {
            Vect2 uv = new Vect2();
            Vect3 x0 = new Vect3();
            Vect3 x1 = new Vect3();

            double[][] uFits = new double[2][];
            double[] sFits = new double[points.Length];
            uFits[0] = new double[points.Length];
            uFits[1] = new double[points.Length];
            //complile fitpoints to fitting arrays
            sFits[0] = 0;
            points[0][0] = 0;
            c.xVal(points[0].UV, ref x0);//initialize starting x point
            for (int nFit = 0; nFit < points.Length; nFit++)
            {
                //sFits[nFit] = fits[nFit][0];
                uFits[0][nFit] = points[nFit][1];
                uFits[1][nFit] = points[nFit][2];

                if (nFit > 0)
                {
                    c.xVal(points[nFit].UV, ref x1);
                    points[nFit][0] = points[nFit - 1][0] + x1.Distance(x0);
                    x0.Set(x1);//store previous x point
                }
            }

            for (int nFit = 0; nFit < points.Length; nFit++)
                sFits[nFit] = points[nFit][0] /= points.Last()[0];//convert length to position
            //sFits[sFits.Length-1] = fits.Last()[0] = 1;//enforce unit length

            c.FitPoints = points;
            c.ReSpline(sFits, uFits);
        }
Beispiel #4
0
        /// <summary>
        /// Interpolates intermediate points in uv and fits a curve
        /// </summary>
        /// <param name="c">the curve to fit</param>
        /// <param name="points">points to fit to, minimum 2</param>
        internal static void InterpoFit(MouldCurve c, IFitPoint[] points)
        {
            if (points.Length <= 1 || points.Length >= 5)//need at least 2 points to fit a curve, can't interpolate more than 4
                return;
            //recalculate s-positions based on xyz-values
            //if (RePos)
            //{
            //	Vect2 uv = new Vect2();
            //	Vect3 x0 = new Vect3();
            //	Vect3 x1 = new Vect3();
            //	fits[0][0] = 0;//initialize s paramter
            //	Surface.xVal(fits[0].UV, ref x0);//initialize starting x point
            //	for (int nFit = 1; nFit < fits.Length; nFit++)
            //	{
            //		Surface.xVal(fits[nFit].UV, ref x1);
            //		fits[nFit][0] = fits[nFit - 1][0] + x1.Distance(x0);
            //		x1.Set(x0);//store previous x point
            //	}
            //	for (int nFit = 0; nFit < fits.Length; nFit++)
            //		fits[nFit][0] /= fits.Last()[0];//convert length to position
            //	fits.Last()[0] = 1;//enforce unit length
            //}

            //linear uv interpolation to match minimum 5 points required

                double[][] uFits = new double[2][];
                double[] sFits = new double[5];
                uFits[0] = new double[5];
                uFits[1] = new double[5];
                double p;
                int i, nint = 0;
                Vect3 x2 = new Vect3(), x1 = new Vect3();
                Vect2 umid = new Vect2();
                Dictionary<int, int> FitstoSFits = new Dictionary<int, int>();
                if (points.Length == 4)
                {
                    //store fitpoints
                    sFits[nint] = points[nint][0] = 0;
                    uFits[0][nint] = points[nint][1];
                    uFits[1][nint] = points[nint][2];
                    c.xVal(points[nint].UV, ref x1);
                    FitstoSFits[nint] = nint;
                    nint++;
                    //store fitpoints
                    //sFits[nint] = fits[nint][0];
                    uFits[0][nint] = points[nint][1];
                    uFits[1][nint] = points[nint][2];
                    c.xVal(points[nint].UV, ref x2);
                    sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                    FitstoSFits[nint] = nint;
                    nint++;
                    //insert midpoint
                    //sFits[nint] = (fits[nint][0] + fits[nint - 1][0]) / 2.0;
                    umid = points[nint].UV + points[nint - 1].UV;
                    umid /= 2;
                    uFits[0][nint] = umid[0];
                    uFits[1][nint] = umid[1];
                    c.xVal(umid, ref x1);
                    sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                    nint++;
                    //store fitpoints
                    //sFits[nint] = fits[nint-1][0];
                    uFits[0][nint] = points[nint - 1][1];
                    uFits[1][nint] = points[nint - 1][2];
                    c.xVal(points[nint - 1].UV, ref x2);
                    sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                    FitstoSFits[nint - 1] = nint;
                    nint++;
                    //store fitpoints
                    //sFits[nint] = fits[nint-1][0];
                    uFits[0][nint] = points[nint - 1][1];
                    uFits[1][nint] = points[nint - 1][2];
                    c.xVal(points[nint - 1].UV, ref x1);
                    sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                    FitstoSFits[nint - 1] = nint;
                    nint++;
                }
                else
                {
                    int num = (5 - points.Length) / (points.Length - 1);//insertion points
                    num = num < 1 ? 1 : num;
                    for (i = 0; i < points.Length - 1; i++)
                    {
                        //store fitpoints
                        //sFits[nint] = fits[i][0];
                        uFits[0][nint] = points[i][1];
                        uFits[1][nint] = points[i][2];
                        FitstoSFits[i] = nint;
                        c.xVal(points[i].UV, ref x1);
                        if (i == 0)
                        {
                            sFits[nint] = 0;
                        }
                        else
                        {
                            sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                        }
                        x2.Set(x1);//store xprev
                        nint++;
                        for (int j = 1; j <= num; j++)
                        {
                            //interpolate insertion points and store
                            p = BLAS.interpolant(j, num + 2);
                            //sFits[nint] = BLAS.interpolate(p, fits[i + 1][0], fits[i][0]);
                            umid[0] = uFits[0][nint] = BLAS.interpolate(p, points[i + 1][1], points[i][1]);
                            umid[1] = uFits[1][nint] = BLAS.interpolate(p, points[i + 1][2], points[i][2]);
                            c.xVal(umid, ref x1);
                            sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                            x2.Set(x1);//store xprev
                            nint++;
                        }
                    }
                    //endpoint
                    //sFits[nint] = 1;
                    uFits[0][nint] = points[i][1];
                    uFits[1][nint] = points[i][2];
                    c.xVal(points[i].UV, ref x1);
                    sFits[nint] = x2.Distance(x1) + sFits[nint - 1];
                    System.Diagnostics.Debug.Assert(nint == 4);
                    FitstoSFits[i] = nint;

                }

                for (i = 0; i < sFits.Length; i++)
                    sFits[i] /= sFits.Last();
                //sFits[sFits.Length - 1] = 1;

                foreach (int key in FitstoSFits.Keys)
                    points[key][0] = sFits[FitstoSFits[key]];

                c.FitPoints = points;
                c.ReSpline(sFits, uFits);
        }
Beispiel #5
0
        /// <summary>
        /// Fits a multi-segement geodesic between the specified fitpoints optionally specifying which segments to girth
        /// </summary>
        /// <param name="points">the array of fitpoints, must be more than 2</param>
        /// <param name="bGirths">an array specifying which segments to girth and which to spline 
        /// count is 1 less than the fitpoints count
        /// can be null which defaults to first and last segment girths</param>
        /// <returns>true if successful, false otherwise</returns>
        internal static bool Geo(MouldCurve g, IFitPoint[] points)
        {
            if (points == null || points.Length < 2)
                return false;
            else if (points.Length == 2 && g.IsGirth(0))
                return Geo(g, points[0], points[1]);

            //compiled piecewise values
            List<double> S = new List<double>();
            List<Vect2> U = new List<Vect2>();

            //segment values
            double[] spos = null;
            Vect2[] upos = null;

            Vect3 xyz = new Vect3(), xyp = new Vect3();

            //initialize S and U
            points[0].S = 0;
            S.Add(0);
            U.Add(points[0].UV);
            for (int i = 1; i < points.Length; i++)
            {
                //span a geo between the fitpoints
                //if (i % 2 == 1)
                if( g.IsGirth(i-1) )
                {
                    if (!GeoSegment(g, points[i - 1], points[i], ref spos, ref upos))
                        return false;

                    for (int nS = 1; nS < spos.Length; nS++)
                    {
                        //scale the spos by length to get distance
                        S.Add(spos[nS] * g.Length + points[i - 1].S);
                        //copy the upos
                        U.Add(upos[nS]);
                    }
                }
                else// if (i % 2 == 0)
                {
                    g.xVal(points[i - 1].UV, ref xyp);
                    g.xVal(points[i].UV, ref xyz);
                    S.Add(xyz.Distance(xyp) + points[i-1].S);
                    U.Add(points[i].UV);
                }
                points[i].S = S.Last();//store the curent length for paramterization
            }

            //reparamaterize
            g.Length = S.Last();
            for (int i = 0; i < S.Count; i++)
                S[i] /= g.Length;

            for (int i = 0; i < points.Length; i++)
                points[i].S /= g.Length;

            //spline the combined points
            g.ReSpline(S.ToArray(), U.ToArray());
            g.FitPoints = points;
            return true;
        }