Пример #1
0
        /// <summary>
        /// create figure using surface function
        /// </summary>
        public void AddSurface(SurfaceFunc func, double x1, double x2, double y1, double y2, double zClosest = 0)
        {
            // calculate surface function values for each point of coordinate grid, and divide grid cell on subcells, if required (for more accurate calculations)

            int xCellCount = (int)Math.Ceiling((x2 - x1) / (PixelWidthInternal / DistanceToEyes * (DistanceToEyes + zClosest)));
            int yCellCount = (int)Math.Ceiling((y2 - y1) / (PixelHeight / DistanceToEyes * (DistanceToEyes + zClosest)));

            var stackFrames = new SurfaceRenderStackFrame[10];

            for (int n = 0; n < stackFrames.Length; n++)
            {
                stackFrames[n] = new SurfaceRenderStackFrame();
            }

            double?[] lineZValues = new double?[xCellCount + 1];
            double    yPrev       = 0;

            for (int yCell = 0; yCell <= yCellCount; yCell++)
            {
                double y = (yCell != yCellCount ? y1 + yCell * (y2 - y1) / yCellCount : y2);

                for (int xCell = 0; xCell <= xCellCount; xCell++)
                {
                    double x = (xCell != xCellCount ? x1 + xCell * (x2 - x1) / xCellCount : x2);

                    double?z = func(x, y);

                    if (yCell != 0)
                    {
                        var firstFrame = stackFrames[0];

                        if (xCell <= 1)
                        {
                            InitPoint(ref firstFrame.Points[xCell == 0 ? 0 : 2, 0], x, yPrev, lineZValues[xCell]);
                            InitPoint(ref firstFrame.Points[xCell == 0 ? 0 : 2, 2], x, y, z);
                        }
                        else
                        {
                            firstFrame.Points[0, 0] = firstFrame.Points[2, 0];
                            firstFrame.Points[0, 2] = firstFrame.Points[2, 2];

                            InitPoint(ref firstFrame.Points[2, 0], x, yPrev, lineZValues[xCell]);
                            InitPoint(ref firstFrame.Points[2, 2], x, y, z);
                        }

                        if (xCell >= 1)
                        {
                            DivideCell(stackFrames, func);
                        }
                    }

                    lineZValues[xCell] = z;
                }

                yPrev = y;
            }
        }
Пример #2
0
        private bool IsDivisionRequired(SurfaceRenderStackFrame stackFrame, SurfaceFunc func)
        {
            // if some points are out of func domain (when grid cell located on domain edge), then use interpolated values

            List <double> zValues = new List <double>(3);

            for (int x1 = 0; x1 <= 2; x1 += 2)
            {
                for (int y1 = 0; y1 <= 2; y1 += 2)
                {
                    if (stackFrame.Points[x1, y1].Z != null)
                    {
                        continue;
                    }

                    zValues.Clear();

                    for (int x2 = 0; x2 <= 2; x2 += 2)
                    {
                        for (int y2 = 0; y2 <= 2; y2 += 2)
                        {
                            if (stackFrame.Points[x2, y2].Z == null)
                            {
                                continue;
                            }

                            double?z = func(stackFrame.Points[x2, y2].X + (stackFrame.Points[x2, y2].X - stackFrame.Points[x1, y1].X) / 100,
                                            stackFrame.Points[x2, y2].Y + (stackFrame.Points[x2, y2].Y - stackFrame.Points[x1, y1].Y) / 100);

                            if (z != null)
                            {
                                zValues.Add(stackFrame.Points[x2, y2].Z.Value + (stackFrame.Points[x2, y2].Z.Value - z.Value) * 100);
                            }
                        }
                    }

                    if (zValues.Count == 0)
                    {
                        return(false);
                    }

                    double zAvg = zValues.Average();

                    stackFrame.Points[x1, y1].XLeftProj  = GetXProj(stackFrame.Points[x1, y1].X, zAvg, true);
                    stackFrame.Points[x1, y1].XRightProj = GetXProj(stackFrame.Points[x1, y1].X, zAvg, false);
                    stackFrame.Points[x1, y1].YProj      = GetYProj(stackFrame.Points[x1, y1].Y, zAvg);
                }
            }

            // if adjacent points of grid with same x or y coordinate are projected to non-adjacent points on the screen, then divide grid cell on subcells

            return(IsDivisionRequired(stackFrame.Points[0, 0].XLeftProj, stackFrame.Points[0, 0].YProj, stackFrame.Points[2, 0].XLeftProj, stackFrame.Points[2, 0].YProj,
                                      stackFrame.Points[2, 2].XLeftProj, stackFrame.Points[2, 2].YProj, stackFrame.Points[0, 2].XLeftProj, stackFrame.Points[0, 2].YProj) ||
                   IsDivisionRequired(stackFrame.Points[0, 0].XRightProj, stackFrame.Points[0, 0].YProj, stackFrame.Points[2, 0].XRightProj, stackFrame.Points[2, 0].YProj,
                                      stackFrame.Points[2, 2].XRightProj, stackFrame.Points[2, 2].YProj, stackFrame.Points[0, 2].XRightProj, stackFrame.Points[0, 2].YProj));
        }
Пример #3
0
 public static Shape PullOnSurface90(this Shape2 shape, SurfaceFunc fn) => new Shape
 {
     Points3  = shape.Points.Select(p => fn(p.y, p.x)).ToArray(),
     Convexes = shape.Convexes
 };
        private bool IsDivisionRequired(SurfaceRenderStackFrame stackFrame, SurfaceFunc func)
        {
            // if some points are out of func domain (when grid cell located on domain edge), then use interpolated values

            List<double> zValues = new List<double>(3);

            for (int x1 = 0; x1 <= 2; x1 += 2)
                for (int y1 = 0; y1 <= 2; y1 += 2)
                {
                    if (stackFrame.Points[x1, y1].Z != null)
                        continue;

                    zValues.Clear();

                    for (int x2 = 0; x2 <= 2; x2 += 2)
                        for (int y2 = 0; y2 <= 2; y2 += 2)
                        {
                            if (stackFrame.Points[x2, y2].Z == null)
                                continue;

                            double? z = func(stackFrame.Points[x2, y2].X + (stackFrame.Points[x2, y2].X - stackFrame.Points[x1, y1].X) / 100,
                             stackFrame.Points[x2, y2].Y + (stackFrame.Points[x2, y2].Y - stackFrame.Points[x1, y1].Y) / 100);

                            if (z != null)
                                zValues.Add(stackFrame.Points[x2, y2].Z.Value + (stackFrame.Points[x2, y2].Z.Value - z.Value) * 100);
                        }

                    if (zValues.Count == 0)
                        return false;

                    double zAvg = zValues.Average();

                    stackFrame.Points[x1, y1].XLeftProj = GetXProj(stackFrame.Points[x1, y1].X, zAvg, true);
                    stackFrame.Points[x1, y1].XRightProj = GetXProj(stackFrame.Points[x1, y1].X, zAvg, false);
                    stackFrame.Points[x1, y1].YProj = GetYProj(stackFrame.Points[x1, y1].Y, zAvg);
                }

            // if adjacent points of grid with same x or y coordinate are projected to non-adjacent points on the screen, then divide grid cell on subcells

            return IsDivisionRequired(stackFrame.Points[0, 0].XLeftProj, stackFrame.Points[0, 0].YProj, stackFrame.Points[2, 0].XLeftProj, stackFrame.Points[2, 0].YProj,
             stackFrame.Points[2, 2].XLeftProj, stackFrame.Points[2, 2].YProj, stackFrame.Points[0, 2].XLeftProj, stackFrame.Points[0, 2].YProj) ||
             IsDivisionRequired(stackFrame.Points[0, 0].XRightProj, stackFrame.Points[0, 0].YProj, stackFrame.Points[2, 0].XRightProj, stackFrame.Points[2, 0].YProj,
             stackFrame.Points[2, 2].XRightProj, stackFrame.Points[2, 2].YProj, stackFrame.Points[0, 2].XRightProj, stackFrame.Points[0, 2].YProj);
        }
        /// <summary>
        /// calculate point projection for some cell and, if required, divide that cell on subcells and repeat procedure for them
        /// </summary>
        private void DivideCell(SurfaceRenderStackFrame[] stackFrames, SurfaceFunc func)
        {
            int depth = 0;
            stackFrames[0].Step = 0;

            while (depth >= 0)
            {
                var currentFrame = stackFrames[depth];

                if (currentFrame.Step == 0)
                {
                    if (depth == stackFrames.Length - 1 || !IsDivisionRequired(currentFrame, func))  // no division required or division limit reached?
                    {
                        // save calculated point projections

                        for (int x = 0; x <= 2; x++)
                            for (int y = 0; y <= 2; y++)
                                if (currentFrame.Points[x, y].Z != null)
                                    AdjustNearest(currentFrame.Points[x, y].XLeftProj, currentFrame.Points[x, y].XRightProj, currentFrame.Points[x, y].YProj);

                        depth--;
                    }
                    else
                    {
                        // calculate additional point coordinates and projections (these values will be used for grid subcells)

                        double[] xCoords = { currentFrame.Points[0, 0].X, (currentFrame.Points[0, 0].X + currentFrame.Points[2, 0].X) / 2, currentFrame.Points[2, 0].X };
                        double[] yCoords = { currentFrame.Points[0, 0].Y, (currentFrame.Points[0, 0].Y + currentFrame.Points[0, 2].Y) / 2, currentFrame.Points[0, 2].Y };

                        for (int x = 0; x <= 2; x++)
                            for (int y = 0; y <= 2; y++)
                                if (x == 1 || y == 1)
                                    InitPoint(ref currentFrame.Points[x, y], xCoords[x], yCoords[y], func(xCoords[x], yCoords[y]));

                        currentFrame.Step++;
                    }
                }
                else if (currentFrame.Step >= 1 && currentFrame.Step <= 4)
                {
                    // initialize next grid subcell and pass to processing of it

                    var nextFrame = stackFrames[depth + 1];
                    nextFrame.Step = 0;

                    for (int x = 0; x <= 1; x++)
                        for (int y = 0; y <= 1; y++)
                            nextFrame.Points[x * 2, y * 2] = currentFrame.Points[(currentFrame.Step - 1) / 2 + x, (currentFrame.Step - 1) % 2 + y];

                    currentFrame.Step++;
                    depth++;
                }
                else
                    depth--;
            }
        }
 /// <param name="zFarthest">determines bounds of the grid (grid must coincide with visible region)</param>
 /// <param name="zClosest">determines base grid cell size</param>
 public void AddSurface(SurfaceFunc func, double zFarthest, double zClosest = 0)
 {
     double addWidth = GetAdditionalWidth(zFarthest), addHeight = GetAdditionalHeight(zFarthest);
     AddSurface(func, -addWidth, Width + addWidth, -addHeight, Height + addHeight, zClosest);
 }
        /// <summary>
        /// create figure using surface function
        /// </summary>
        public void AddSurface(SurfaceFunc func, double x1, double x2, double y1, double y2, double zClosest = 0)
        {
            // calculate surface function values for each point of coordinate grid, and divide grid cell on subcells, if required (for more accurate calculations)

            int xCellCount = (int)Math.Ceiling((x2 - x1) / (PixelWidthInternal / DistanceToEyes * (DistanceToEyes + zClosest)));
            int yCellCount = (int)Math.Ceiling((y2 - y1) / (PixelHeight / DistanceToEyes * (DistanceToEyes + zClosest)));

            var stackFrames = new SurfaceRenderStackFrame[10];
            for (int n = 0; n < stackFrames.Length; n++)
                stackFrames[n] = new SurfaceRenderStackFrame();

            double?[] lineZValues = new double?[xCellCount + 1];
            double yPrev = 0;

            for (int yCell = 0; yCell <= yCellCount; yCell++)
            {
                double y = (yCell != yCellCount ? y1 + yCell * (y2 - y1) / yCellCount : y2);

                for (int xCell = 0; xCell <= xCellCount; xCell++)
                {
                    double x = (xCell != xCellCount ? x1 + xCell * (x2 - x1) / xCellCount : x2);

                    double? z = func(x, y);

                    if (yCell != 0)
                    {
                        var firstFrame = stackFrames[0];

                        if (xCell <= 1)
                        {
                            InitPoint(ref firstFrame.Points[xCell == 0 ? 0 : 2, 0], x, yPrev, lineZValues[xCell]);
                            InitPoint(ref firstFrame.Points[xCell == 0 ? 0 : 2, 2], x, y, z);
                        }
                        else
                        {
                            firstFrame.Points[0, 0] = firstFrame.Points[2, 0];
                            firstFrame.Points[0, 2] = firstFrame.Points[2, 2];

                            InitPoint(ref firstFrame.Points[2, 0], x, yPrev, lineZValues[xCell]);
                            InitPoint(ref firstFrame.Points[2, 2], x, y, z);
                        }

                        if (xCell >= 1)
                            DivideCell(stackFrames, func);
                    }

                    lineZValues[xCell] = z;
                }

                yPrev = y;
            }
        }
Пример #8
0
 public SurfaceDyno(SurfaceFunc surfaceFunc, Vector2[] uvPoints, (int i, int j)[] connections, Func <Graph.Node, DynoFunc> ruleFn)
Пример #9
0
        /// <param name="zFarthest">determines bounds of the grid (grid must coincide with visible region)</param>
        /// <param name="zClosest">determines base grid cell size</param>
        public void AddSurface(SurfaceFunc func, double zFarthest, double zClosest = 0)
        {
            double addWidth = GetAdditionalWidth(zFarthest), addHeight = GetAdditionalHeight(zFarthest);

            AddSurface(func, -addWidth, Width + addWidth, -addHeight, Height + addHeight, zClosest);
        }
Пример #10
0
        /// <summary>
        /// calculate point projection for some cell and, if required, divide that cell on subcells and repeat procedure for them
        /// </summary>
        private void DivideCell(SurfaceRenderStackFrame[] stackFrames, SurfaceFunc func)
        {
            int depth = 0;

            stackFrames[0].Step = 0;

            while (depth >= 0)
            {
                var currentFrame = stackFrames[depth];

                if (currentFrame.Step == 0)
                {
                    if (depth == stackFrames.Length - 1 || !IsDivisionRequired(currentFrame, func))                      // no division required or division limit reached?
                    {
                        // save calculated point projections

                        for (int x = 0; x <= 2; x++)
                        {
                            for (int y = 0; y <= 2; y++)
                            {
                                if (currentFrame.Points[x, y].Z != null)
                                {
                                    AdjustNearest(currentFrame.Points[x, y].XLeftProj, currentFrame.Points[x, y].XRightProj, currentFrame.Points[x, y].YProj);
                                }
                            }
                        }

                        depth--;
                    }
                    else
                    {
                        // calculate additional point coordinates and projections (these values will be used for grid subcells)

                        double[] xCoords = { currentFrame.Points[0, 0].X, (currentFrame.Points[0, 0].X + currentFrame.Points[2, 0].X) / 2, currentFrame.Points[2, 0].X };
                        double[] yCoords = { currentFrame.Points[0, 0].Y, (currentFrame.Points[0, 0].Y + currentFrame.Points[0, 2].Y) / 2, currentFrame.Points[0, 2].Y };

                        for (int x = 0; x <= 2; x++)
                        {
                            for (int y = 0; y <= 2; y++)
                            {
                                if (x == 1 || y == 1)
                                {
                                    InitPoint(ref currentFrame.Points[x, y], xCoords[x], yCoords[y], func(xCoords[x], yCoords[y]));
                                }
                            }
                        }

                        currentFrame.Step++;
                    }
                }
                else if (currentFrame.Step >= 1 && currentFrame.Step <= 4)
                {
                    // initialize next grid subcell and pass to processing of it

                    var nextFrame = stackFrames[depth + 1];
                    nextFrame.Step = 0;

                    for (int x = 0; x <= 1; x++)
                    {
                        for (int y = 0; y <= 1; y++)
                        {
                            nextFrame.Points[x * 2, y * 2] = currentFrame.Points[(currentFrame.Step - 1) / 2 + x, (currentFrame.Step - 1) % 2 + y];
                        }
                    }

                    currentFrame.Step++;
                    depth++;
                }
                else
                {
                    depth--;
                }
            }
        }