Esempio n. 1
0
        /// <summary>
        /// Snap End and Start points for each curve in list 'curves2d' (new point is avarage of both)
        /// If found singularity -
        /// 1) add index of curve2d after wich need to add singular trim in list 'singulars'
        /// 2) snap Start and End points to the corner of surface where Singularity exists
        /// </summary>
        /// <param name="srf"></param>
        /// <param name="curves2d">list of curves in UV projection for sruface 'srf'</param>
        /// <param name="singulars">Will contain index of curve2d after which need to add singularity</param>
        public static void _SnapCurves2d(this Surface srf, List <NurbsCurve> curves2d, out List <int> singulars)
        {
            var domainU = srf.Domain(0);
            var domainV = srf.Domain(1);

            singulars = new List <int>();

            for (int i = 0; i < curves2d.Count; i++)
            {
                int iEnd   = i - 1;
                int iStart = i;
                if (iStart == 0)
                {
                    iEnd = curves2d.Count - 1;
                }
                var pointStart = new SurfacePoint(curves2d[iStart].PointAtStart);
                var pointEnd   = new SurfacePoint(curves2d[iEnd].PointAtEnd);

                var diffU = Math.Abs(pointStart.u - pointEnd.u);
                var diffV = Math.Abs(pointStart.v - pointEnd.v);
                if (diffU < 0.01 * domainU.Length && diffV < 0.01 * domainV.Length)
                {
                    var avarageU     = (pointStart.u + pointEnd.u) / 2;
                    var avarageV     = (pointStart.v + pointEnd.v) / 2;
                    var avaragePoint = new Point3d(avarageU, avarageV, 0);
                    curves2d[iStart].SetStartPoint(avaragePoint);
                    curves2d[iEnd].SetEndPoint(avaragePoint);
                    curves2d[iStart].Points.SetPoint(0, avaragePoint);
                    curves2d[iEnd].Points.SetPoint(curves2d[iEnd].Points.Count - 1, avaragePoint);
                }
                else
                {
                    var pointStart3d        = srf.PointAt(pointStart.u, pointStart.v);
                    var pointEnd3d          = srf.PointAt(pointEnd.u, pointEnd.v);
                    var distance3d          = pointEnd3d._DistanceTo(pointStart3d);
                    var isExtremSingularity = distance3d < _Double.ZERO;
                    var isNormalSingularity = (distance3d < 0.001) &&
                                              (diffU > domainU.Length / 7 || diffV > domainV.Length / 7);
                    if (isExtremSingularity || isNormalSingularity) // singularity present
                    {
                        // round start and end points to mutch surface corner in singularity
                        var pointAtStart = curves2d[iStart].PointAtStart._RoundToDomain(domainU, domainV);
                        curves2d[iStart].SetStartPoint(pointAtStart);
                        var pointAtEnd = curves2d[iEnd].PointAtEnd._RoundToDomain(domainU, domainV);
                        curves2d[iEnd].SetEndPoint(pointAtEnd);
                        singulars.Add(iEnd);
                    }
                    else
                    {
                        throw new Exception("Can't snap Curves2d at index " + i);
                    }
                }
            }

            singulars.Sort();
        }
Esempio n. 2
0
        /// <summary>
        /// Get centroid of surface base on avarage 3d points devided by paramter 'divby'.
        /// If 'divby' is zero - 'srf.PointAt(uDomain.Mid, vDomain.Mid)' will be returned.
        /// </summary>
        /// <param name="srf"></param>
        /// <param name="loopEdges">all edges of loop</param>
        /// <param name="accurate">Accurate takes more time but have great precision.</param>
        /// <returns></returns>
        public static Point3d _GetCentroid(this Surface srf, Curve[] loopEdges, bool accurate)
        {
            // Get edges points
            var MAX_EDGE_POINTS        = accurate ? 1000 : 500;
            var edgesPoints            = new List <Point3d>();
            var prevPointAtStart       = Point3d.Origin;
            var prevPointAtEnd         = Point3d.Origin;
            var edgesLengths           = loopEdges.Select(o => o._GetLength_ThreadSafe()).ToList();
            var divbyTol               = accurate ? 0.01 : 0.1;
            var desiredEdgePointsCount = edgesLengths.Sum() / divbyTol;

            if (desiredEdgePointsCount > MAX_EDGE_POINTS)
            {
                divbyTol = edgesLengths.Sum() / MAX_EDGE_POINTS; // limit edge point at approximatelly 1000 points
            }
            for (var i = 0; i < loopEdges.Length; i++)
            {
                var       edge  = loopEdges[i];
                var       divby = edge._GetDivBy(edgesLengths[i], divbyTol, 0);
                Point3d[] points;
                if (edge._TryDivideByCount(divby, out points) && points.Length >= 2)
                {
                    var deleteDuplicatePointIndex = -1;// index of point3d that id duplicated for 2 edges (some connection point)
                    if (edgesPoints.Count != 0)
                    {
                        var distToStart = Math.Min(points.First()._DistanceTo(prevPointAtStart), points.First()._DistanceTo(prevPointAtEnd));
                        var distToEnd   = Math.Min(points.Last()._DistanceTo(prevPointAtStart), points.Last()._DistanceTo(prevPointAtEnd));
                        if (distToStart < distToEnd && distToStart < 0.001)
                        {
                            deleteDuplicatePointIndex = edgesPoints.Count;
                        }
                        else if (distToEnd < distToStart && distToEnd < 0.001)
                        {
                            deleteDuplicatePointIndex = edgesPoints.Count + points.Length - 1;
                        }
                    }
                    edgesPoints.AddRange(points);
                    // remove duplicate point if such exists - this will increate accuracy
                    if (deleteDuplicatePointIndex != -1)
                    {
                        edgesPoints.RemoveAt(deleteDuplicatePointIndex);
                    }
                    prevPointAtStart = points.First(); // remember PointAtStart of last edge
                    prevPointAtEnd   = points.Last();  // remember PointAtStart of last edge
                    //Layers.Debug.AddPoints(points, Color.Black);
                }
            }

            // Limit edge points to 1000 - speed improvement (we can have here 26000 points what take 3 seconds of time - to much)
            int skipp = edgesPoints.Count / MAX_EDGE_POINTS;

            if (skipp > 1)
            {
                var edgesPoints_limited = new List <Point3d>(MAX_EDGE_POINTS * 2);
                var i = 0;
                while (i < edgesPoints.Count)
                {
                    edgesPoints_limited.Add(edgesPoints[i]);
                    i += skipp;
                }
                edgesPoints = edgesPoints_limited;
            }

            // detect interval where loop is inside - this will make our calculation more accurate for small loops of big surfaces
            //var edgesPointsOnSrf = srf._ClosestPoints(edgesPoints);
            //var uDomain = new Interval(edgesPointsOnSrf.Select(o => o.u).Min(), edgesPointsOnSrf.Select(o => o.u).Max());
            //var vDomain = new Interval(edgesPointsOnSrf.Select(o => o.v).Min(), edgesPointsOnSrf.Select(o => o.v).Max());

            var uDomain = srf.Domain(0);
            var vDomain = srf.Domain(1);



            var iterationNum      = 0;
            var iterationCentroid = Point3d.Origin;
            var domain3dLength    = Double.MaxValue;
            var iterationsMax     = accurate ? 50 : 10;
            var iterationDomain3dLengthEnought = accurate ? 0.0001 : 0.001;

            while (iterationNum < iterationsMax &&
                   domain3dLength > iterationDomain3dLengthEnought)
            {
                // Get srf points
                var srfPoints2d = srf._GetDivby2dPoints(4, uDomain, vDomain);
                if (srfPoints2d.Length == 0)
                {
                    break;
                }
                var srfPoints3d   = srfPoints2d.Select(o => srf.PointAt(o.u, o.v)).ToArray();
                var bestDist_Pow2 = Double.MaxValue;
                var best2dPoint   = new SurfacePoint(0, 0);
                var best3dPoint   = Point3d.Origin;
                var bestIndex     = -1;
                domain3dLength = Double.MaxValue;
                for (var i = 0; i < srfPoints2d.Length; i++)
                {
                    var p2d = srfPoints2d[i];
                    var p3d = srfPoints3d[i];
                    //var summ3dDists_Pow2 = edgesPoints.Select(ep => ep._DistanceTo_Pow2(p3d)).Sum();
                    double summ3dDists_Pow2 = 0;
                    for (int k = 0; k < edgesPoints.Count; k++)
                    {
                        summ3dDists_Pow2 += p3d._DistanceTo_Pow2(edgesPoints[k]);
                    }
                    if (summ3dDists_Pow2 < bestDist_Pow2)
                    {
                        bestDist_Pow2 = summ3dDists_Pow2;
                        best2dPoint   = p2d;
                        best3dPoint   = p3d;
                        bestIndex     = i;
                    }
                    //Layers.Debug.AddPoint(p3d, Color.Wheat);
                }
                //Layers.Debug.AddPoint(best3dPoint, Color.Red);
                iterationNum++;
                iterationCentroid = best3dPoint;
                var domainSrfMidPoint = srf.PointAt(uDomain.Mid, vDomain.Mid);
                domain3dLength = Math.Min(domain3dLength, domainSrfMidPoint._DistanceTo(srfPoints3d.First()));
                domain3dLength = Math.Min(domain3dLength, domainSrfMidPoint._DistanceTo(srf.PointAt(uDomain.T0, vDomain.T1)));
                domain3dLength = Math.Min(domain3dLength, domainSrfMidPoint._DistanceTo(srf.PointAt(uDomain.T1, vDomain.T0)));
                domain3dLength = Math.Min(domain3dLength, domainSrfMidPoint._DistanceTo(srfPoints3d.Last()));
                uDomain        = new Interval(best2dPoint.u - uDomain.Length / 4, best2dPoint.u + uDomain.Length / 4);
                vDomain        = new Interval(best2dPoint.v - vDomain.Length / 4, best2dPoint.v + vDomain.Length / 4);
            }

            //Layers.Debug.AddTextPoint("_BrepLoop._GetCentroid", iterationCentroid, Color.Red);
            return(iterationCentroid);
        }