public override GeoPoint2D PositionOf(GeoPoint p)
        {
            GeoPoint2D uvp = periodicSurface.PositionOf(p);

            SurfaceHelper.AdjustPeriodic(periodicSurface, periodicBounds, ref uvp);
            return(fromPeriodic(uvp));
        }
        public ISurface AdaptToCurves(IEnumerable <ICurve> curves)
        {
            BoundingRect domain = BoundingRect.EmptyBoundingRect;

            foreach (ICurve curve in curves)
            {
                ICurve2D c2d = periodicSurface.GetProjectedCurve(curve, 0.0);
                if (domain.IsEmpty())
                {
                    domain = c2d.GetExtent();
                }
                else
                {
                    SurfaceHelper.AdjustPeriodic(periodicSurface, domain, c2d);
                    domain.MinMax(c2d.GetExtent());
                }
            }
            return(new NonPeriodicSurface(periodicSurface, domain));
        }
Beispiel #3
0
        protected override void GetTriangulationBasis(out GeoPoint2D[] points, out GeoVector2D[] directions, out double[] parameters)
        {
            double[]      pars      = curve3D.GetSavePositions();
            List <double> positions = new List <double>();

            for (int i = 0; i < pars.Length; i++)
            {
                double d = Get2dParameter(pars[i]);
                if (d > 1e-6 && d < 1.0 - 1e-6)
                {
                    positions.Add(d);                             // nur innerhalb des Bereichs und 0 und 1 nicht doppelt
                }
            }
            positions.Add(0.0);
            positions.Add(1.0);
            if (positions.Count < 3)
            {
                positions.Add(0.5);
            }
            positions.Sort();
            List <double> lparameters = new List <double>();

            for (int i = 0; i < positions.Count; i++)
            {
                lparameters.Add(positions[i]);
            }
            List <GeoPoint2D>  lpoints     = new List <GeoPoint2D>();
            List <GeoVector2D> ldirections = new List <GeoVector2D>();

            for (int i = 0; i < positions.Count; i++)
            {
                GeoPoint2D  p;
                GeoVector2D v;
                PointDirAt(positions[i], out p, out v);
                lpoints.Add(p);
                ldirections.Add(v);
            }

            bool check = true;

            // the interpolation should be smooth. Max. bending between interpolation points 45°, which makes sure, the baseApproximation
            // uses arcs, so that the start- and end-direction are correct
            while (check && lpoints.Count < 100)
            {
                check = false;
                for (int i = lpoints.Count - 1; i > 0; --i)
                {
                    if (Math.Abs(new SweepAngle(ldirections[i], ldirections[i - 1])) > Math.PI / 4)
                    {
                        double      par = (positions[i] + positions[i - 1]) / 2.0;
                        GeoPoint2D  p   = PointAt(par);
                        GeoVector2D dir = DirectionAt(par);
                        lpoints.Insert(i, p);
                        ldirections.Insert(i, dir);
                        positions.Insert(i, par);
                        check = true;
                    }
                }
            }
            points     = lpoints.ToArray();
            directions = ldirections.ToArray();
            parameters = positions.ToArray();
            if (surface.IsUPeriodic)
            {
                for (int i = 1; i < points.Length; i++)
                {
                    if ((points[i].x - points[i - 1].x) > surface.UPeriod / 2.0)
                    {
                        points[i].x -= surface.UPeriod;
                    }
                    if ((points[i].x - points[i - 1].x) < -surface.UPeriod / 2.0)
                    {
                        points[i].x += surface.UPeriod;
                    }
                }
            }
            if (surface.IsVPeriodic)
            {
                for (int i = 1; i < points.Length; i++)
                {
                    if ((points[i].y - points[i - 1].y) > surface.VPeriod / 2.0)
                    {
                        points[i].y -= surface.VPeriod;
                    }
                    if ((points[i].y - points[i - 1].y) < -surface.VPeriod / 2.0)
                    {
                        points[i].y += surface.VPeriod;
                    }
                }
            }
            if (!periodicDomain.IsEmpty())
            {
                SurfaceHelper.AdjustPeriodic(surface, periodicDomain, points);
            }
        }
Beispiel #4
0
        private int debugCount; // to identify instance when debugging
#endif

        public ProjectedCurve(ICurve curve3D, ISurface surface, bool forward, BoundingRect domain, double precision = 0.0)
        {
#if DEBUG
            debugCount = debugCounter++;
#endif
            this.curve3D = curve3D; // keep in mind, the curve is not cloned, curve3D should not be modified after this
            this.surface = surface;
            List <GeoPoint>   lpoles   = new List <GeoPoint>();
            List <GeoPoint2D> lpoles2d = new List <GeoPoint2D>();
            GeoPoint2D        cnt2d    = domain.GetCenter();
            GeoPoint          sp       = curve3D.StartPoint;
            GeoPoint          ep       = curve3D.EndPoint;
            double[]          us       = surface.GetUSingularities();
            double            prec     = precision;
            if (prec == 0.0)
            {
                prec = curve3D.Length * 1e-3;              // changed to 1e-3, it is used to snap endpoints to poles
            }
            startPoint2d = surface.PositionOf(curve3D.StartPoint);
            endPoint2d   = surface.PositionOf(curve3D.EndPoint);
            bool distinctStartEndPoint = false;
            if ((surface.IsUPeriodic && Math.Abs(startPoint2d.x - endPoint2d.x) < surface.UPeriod * 1e-3) ||
                (surface.IsVPeriodic && Math.Abs(startPoint2d.y - endPoint2d.y) < surface.VPeriod * 1e-3))
            {   // adjust start and endpoint according to its neighbors
                GeoPoint2D p2d = surface.PositionOf(curve3D.PointAt(0.1));
                SurfaceHelper.AdjustPeriodic(surface, periodicDomain, ref p2d);
                BoundingRect ext = new BoundingRect(p2d);
                SurfaceHelper.AdjustPeriodic(surface, ext, ref startPoint2d);
                p2d = surface.PositionOf(curve3D.PointAt(0.9));
                SurfaceHelper.AdjustPeriodic(surface, periodicDomain, ref p2d);
                ext = new BoundingRect(p2d);
                SurfaceHelper.AdjustPeriodic(surface, ext, ref endPoint2d);
                distinctStartEndPoint = true;
            }
            periodicDomain = domain;
            if (periodicDomain.IsEmpty() && (surface.IsUPeriodic || surface.IsVPeriodic))
            {
                // make a few points and assure that they don't jump over the periodic seam
                // if the curve3d doesn't jump around wildly, this should work. Maybe use curve3D.GetSavePositions?
                GeoPoint2D[] point2Ds = new GeoPoint2D[11];
                for (int i = 0; i < 11; i++)
                {
                    point2Ds[i] = surface.PositionOf(curve3D.PointAt(i / 10.0));
                }
                for (int i = 0; i < 10; i++)
                {
                    GeoVector2D offset = GeoVector2D.NullVector;
                    if (surface.IsUPeriodic && Math.Abs(point2Ds[i + 1].x - point2Ds[i].x) > surface.UPeriod / 2.0)
                    {
                        if ((point2Ds[i + 1].x - point2Ds[i].x) < 0)
                        {
                            offset.x = surface.UPeriod;
                        }
                        else
                        {
                            offset.x = -surface.UPeriod;
                        }
                    }
                    if (surface.IsVPeriodic && Math.Abs(point2Ds[i + 1].y - point2Ds[i].y) > surface.VPeriod / 2.0)
                    {
                        if ((point2Ds[i + 1].y - point2Ds[i].y) < 0)
                        {
                            offset.y = surface.VPeriod;
                        }
                        else
                        {
                            offset.y = -surface.VPeriod;
                        }
                    }
                    point2Ds[i + 1] += offset;
                }
                for (int i = 0; i < 11; i++)
                {
                    periodicDomain.MinMax(point2Ds[i]);
                }
                startPoint2d = point2Ds[0];
                endPoint2d   = point2Ds[10];
            }
            if (!periodicDomain.IsEmpty() && (!surface.IsUPeriodic || periodicDomain.Width < surface.UPeriod * (1 - 1e-6)) && (!surface.IsVPeriodic || periodicDomain.Height < surface.VPeriod * (1 - 1e-6)))
            {
                SurfaceHelper.AdjustPeriodic(surface, periodicDomain, ref startPoint2d);
                SurfaceHelper.AdjustPeriodic(surface, periodicDomain, ref endPoint2d);
            }
            startPointIsPole = endPointIsPole = false;
            for (int i = 0; i < us.Length; i++)
            {
                GeoPoint pl = surface.PointAt(new GeoPoint2D(us[i], cnt2d.y));
                if ((pl | sp) < prec)
                {
                    GeoPoint2D tmp = surface.PositionOf(curve3D.PointAt(0.1));
                    startPoint2d     = new GeoPoint2D(us[i], tmp.y);
                    startPointIsPole = true;
                    spu = true;
                }
                if ((pl | ep) < prec)
                {
                    GeoPoint2D tmp = surface.PositionOf(curve3D.PointAt(0.9));
                    endPoint2d     = new GeoPoint2D(us[i], tmp.y);
                    endPointIsPole = true;
                    epu            = true;
                }
            }
            double[] vs = surface.GetVSingularities();
            for (int i = 0; i < vs.Length; i++)
            {
                GeoPoint pl = surface.PointAt(new GeoPoint2D(cnt2d.x, vs[i]));
                if ((pl | sp) < prec)
                {
                    GeoPoint2D tmp = surface.PositionOf(curve3D.PointAt(0.1));
                    startPoint2d     = new GeoPoint2D(tmp.x, vs[i]);
                    startPointIsPole = true;
                    spu = false;
                }
                if ((pl | ep) < prec)
                {
                    GeoPoint2D tmp = surface.PositionOf(curve3D.PointAt(0.9));
                    endPoint2d     = new GeoPoint2D(tmp.x, vs[i]);
                    endPointIsPole = true;
                    epu            = false;
                }
            }
            if (forward)
            {
                startParam = 0.0;
                endParam   = 1.0;
            }
            else
            {
                startParam = 1.0;
                endParam   = 0.0;
            }
#if DEBUG
            this.MakeTriangulation();
#endif
        }