Exemple #1
0
        private void InitializeThinSearch(double thinThickness, double xBasis, double yBasis, List <SearchPoint> pattern)
        {
            // simply loop through all pixels that could possibly be closer than
            // a half pixel from a line through (0,0) and parallel to the basis vector
            int ijmax = (int)(thinThickness + 0.5) + 1;

            for (int j = -ijmax; j <= ijmax; j++)
            {
                for (int i = -ijmax; i <= ijmax; i++)
                {
                    double x = (double)i;
                    double y = (double)j;

                    // this point must be in same direction as the basis vector. use dot product
                    if (x * xBasis + y * yBasis > 0)
                    {
                        // this point must be within a half pixel of the basis vector
                        if (NuGenMath.DistanceToLine(x, y, 0.0, 0.0, xBasis, yBasis) <= 0.5)
                        {
                            // add new search point
                            SearchPoint p = new SearchPoint(i, j, Math.Sqrt(i * i + j * j));

                            pattern.Add(p);
                        }
                    }
                }
            }

            pattern.Sort();
        }
Exemple #2
0
        // return the area and distance geometry info for this pointset
        private void GeometryInfoArea(ref int pNextRow, List <NuGenGeometryWindowItem> rInfo)
        {
            double funcArea = 0.0, polyArea = 0.0;
            int    i = 0, nPoints = points.Count;

            if (nPoints > 2)
            {
                double[] x = new double[nPoints];
                double[] y = new double[nPoints];

                foreach (NuGenPoint point in points)
                {
                    x[i] = point.XThetaGraph;
                    y[i] = point.YRGraph;
                    i++;
                }

                funcArea = NuGenMath.FunctionArea(nPoints, x, y);
                polyArea = NuGenMath.PolygonArea(nPoints, x, y);
            }

            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 0, "FuncArea"));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 1, funcArea.ToString()));

            pNextRow++;

            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 0, "PolyArea"));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 1, polyArea.ToString()));

            pNextRow++;
        }
Exemple #3
0
        // compute pleasing gridMeshSettings display line settings, returning true if successful
        public void InitGridMesh(ref GridMeshSettings gridSettings)
        {
            gridSettings.initialized = false;

            if (!transform.ValidAxes)
            {
                return;
            }

            gridSettings.gridSetX = GridSet.AllButStep;
            gridSettings.gridSetY = GridSet.AllButStep;

            double xThetaMin = 0.0, xThetaMax = 0.0, yRMin = 0.0, yRMax = 0.0;

            pointSets.PointSetGraphLimits(coordSettings, transform,
                                          ref xThetaMin, ref xThetaMax, ref yRMin, ref yRMax);

            NuGenMath.AxisScale(xThetaMin, xThetaMax, (coordSettings.xThetaScale == Scale.Linear),
                                out gridSettings.startX,
                                out gridSettings.stopX,
                                out gridSettings.stepX,
                                out gridSettings.countX);
            NuGenMath.AxisScale(yRMin, yRMax, (coordSettings.yRScale == Scale.Linear),
                                out gridSettings.startY,
                                out gridSettings.stopY,
                                out gridSettings.stepY,
                                out gridSettings.countY);

            gridSettings.initialized = true;
        }
Exemple #4
0
        private static List <GridlineScreen> MakeGridR(NuGenScreenTranslate transform, CoordSettings coordSettings, GridMeshSettings gridMeshSettings)
        {
            int                   i;
            int                   xStartS = 0, yStartS = 0, xStopS = 1, yStopS = 1;
            double                rG = gridMeshSettings.startY;
            GridlineScreen        gridline;
            List <GridlineScreen> gridlines = new List <GridlineScreen>();

            for (i = 0; i < gridMeshSettings.countY; i++)
            {
                gridline = new GridlineScreen();
                // for polar coordinates we simply piecewise define the elliptical arc until motivated
                // to implement a better drawing algorithm. segments will be evenly spaced in angle
                // some pdf documents describing alternative algorithms are found in the doc directory.
                // it would have been elegant to use QCanvasEllipses but those are axis-aligned.
                double delta = AngleSpacing(coordSettings.thetaUnits);
                bool   first = true;
                for (double angle = gridMeshSettings.startX; angle < gridMeshSettings.stopX; angle += delta)
                {
                    transform.XThetaYRToScreen(coordSettings, angle, rG, out xStopS, out yStopS);

                    if (first)
                    {
                        xStartS = xStopS;
                        yStartS = yStopS;
                    }
                    else
                    {
                        if (NuGenMath.VectorMagnitude(xStopS - xStartS, yStopS - yStartS, 0.0) >= pixelSpacing)
                        {
                            gridline.Start.X = xStartS;
                            gridline.Start.Y = yStartS;
                            gridline.Stop.X  = xStopS;
                            gridline.Stop.Y  = yStopS;
                            gridline.R       = true;

                            xStartS = xStopS;
                            yStartS = yStopS;
                        }
                    }

                    first = false;
                }

                if (coordSettings.yRScale == Scale.Linear)
                {
                    rG += gridMeshSettings.stepY;
                }
                else
                {
                    rG *= gridMeshSettings.stepY;
                }
            }

            return(gridlines);
        }
Exemple #5
0
        bool PointIsCloseToLine(double xLeft, double yLeft, double xInt, double yInt,
                                double xRight, double yRight)
        {
            double xProj, yProj;

            NuGenMath.ProjectPointOnToLine(xInt, yInt, xLeft, yLeft, xRight, yRight, out xProj, out yProj);

            return(
                (xInt - xProj) * (xInt - xProj) +
                (yInt - yProj) * (yInt - yProj) < 0.5 * 0.5);
        }
Exemple #6
0
 private static void TestMatrixMultiplication()
 {
     double[][] mat1 = { new double[3] {
                             3, 3, 3
                         }, new double[3]{
                             3, 3, 3
                         }, new double[3]{
                             3, 3, 3
                         } };
     double[,] mat2 = { { 3, 3, 3 }, { 3, 3, 3 }, { 3, 3, 3 } };
     double[,] res  = new double[3, 3];
     NuGenMath.MatrixMultiply3x3(res, mat1, mat2);
 }
        //Converts a pair of screen coordinates to graph coordinates
        private void ScreenToGraph(double xScreen, double yScreen, out double xGraph, out double yGraph)
        {
            double[] rScreen = new double[3];
            double[] rGraph  = new double[3];

            rScreen[0] = xScreen;
            rScreen[1] = yScreen;
            rScreen[2] = 1.0;

            NuGenMath.MatrixMultiply3x1(rGraph, screenToGraph, rScreen);

            xGraph = rGraph[0];
            yGraph = rGraph[1];
        }
Exemple #8
0
        // add point to pointset, not worrying about keeping the pointset single valued (which is for
        // curves only). if new point is on the line between two points then insert it between
        // those two points (desired behavior for curve and measure pointsets, which happens to not affect
        // axes and scale pointsets)
        public void AddPoint(NuGenPoint point)
        {
            // insert point between two other points if it lies on the line between the two points
            const int  LineEpsilonPixels = 2;
            int        index             = 0;
            double     x    = point.XScreen;
            double     y    = point.YScreen;
            NuGenPoint pOld = null;

            foreach (NuGenPoint pNew in points)
            {
                double xNew = pNew.XScreen;
                double yNew = pNew.YScreen;

                if (pOld != null)
                {
                    double xOld = pOld.XScreen;
                    double yOld = pOld.YScreen;

                    double xProj, yProj;
                    NuGenMath.ProjectPointOnToLine(x, y, xOld, yOld, xNew, yNew, out xProj, out yProj);

                    double diff = Math.Sqrt((x - xProj) * (x - xProj) + (y - yProj) * (y - yProj));
                    if (diff < LineEpsilonPixels)
                    {
                        points.Insert(index, point);
                        point.PointSet = this;

                        RemoveLine(pOld, pNew);
                        AddLine(pOld, point);
                        AddLine(point, pNew);

                        return;
                    }
                }

                pOld = pNew;
                index++;
            }

            points.Add(point);
            point.PointSet = this;

            if (pOld != null)
            {
                AddLine(pOld, point);
            }
        }
        public void XThetaYRToScreen(CoordSettings coordSettings, double xTheta, double yR, out double xScreen, out double yScreen)
        {
            if (ValidAxes || ValidScale)
            {
                LinearToLog(coordSettings, ref xTheta, ref yR);

                double xGraph, yGraph;
                ConvertToCartesian(NuGenMath.mmUnitize(coordSettings), xTheta, yR, out xGraph, out yGraph);

                GraphToScreen(xGraph, yGraph, out xScreen, out yScreen);
            }
            else
            {
                xScreen = xTheta;
                yScreen = yR;
            }
        }
Exemple #10
0
        private void GeometryInfoDistancePass1(int i, NuGenPoint pointNext,
                                               double xLast, double yLast, double x, double y,
                                               double distance, double totalDistance, ref int pNextRow, List <NuGenGeometryWindowItem> rInfo)
        {
            double xNext = pointNext.XThetaGraph;
            double yNext = pointNext.YRGraph;

            double pcDistance;

            if (totalDistance <= 0.0)
            {
                pcDistance = 100.0;
            }
            else
            {
                pcDistance = 100.0 * distance / totalDistance;
            }

            double[] r1 = new double[3];
            double[] r2 = new double[3];

            r1[0] = xLast - x; // xLast from last point of pass 0 is used by first point in pass 1
            r1[1] = yLast - y; // yLast from last point of pass 0 is used by first point in pass 1
            r1[2] = 0.0;
            r2[0] = xNext - x;
            r2[1] = yNext - y;
            r2[2] = 0.0;

            double angle = NuGenMath.Angle(r1, r2) * 180.0 / Math.PI;

            double distDiff = totalDistance - distance;
            double pcDiff   = 100.0 - pcDistance;

            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 0, x.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 1, y.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 2, i.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 3, distance.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 4, pcDistance.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 5, distDiff.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 6, pcDiff.ToString()));
            rInfo.Add(new NuGenGeometryWindowItem(pNextRow, 7, angle.ToString()));

            pNextRow++;
        }
        //Converts a screen coordinate pair to a graph coordinate pair
        public void ScreenToXThetaYR(CoordSettings coordSettings, double xScreen, double yScreen, out double xTheta, out double yR)
        {
            if (ValidAxes || ValidScale)
            {
                double xGraph, yGraph;
                ScreenToGraph(xScreen, yScreen, out xGraph, out yGraph);

                ConvertFromCartesian(NuGenMath.mmUnitize(coordSettings), xGraph, yGraph, out xTheta, out yR);

                LogToLinear(coordSettings, ref xTheta, ref yR);
            }
            else
            {
                // until transform is defined just use identity matrix. this branch is only defined when trying
                // to connect points with lines, and the transform is not currently defined
                xTheta = xScreen;
                yR     = yScreen;
            }
        }
        //Converts a pair of graph coordinates to screen coordinates
        private void GraphToScreen(double xGraph, double yGraph, out double xScreen, out double yScreen)
        {
            if (!(ValidAxes || ValidScale))
            {
                throw new InvalidOperationException("No valid axes or scale");
            }

            double[] rScreen = new double[3];
            double[] rGraph  = new double[3];

            rGraph[0] = xGraph;
            rGraph[1] = yGraph;
            rGraph[2] = 1.0;

            NuGenMath.MatrixMultiply3x1(rScreen, graphToScreen, rGraph);

            xScreen = rScreen[0];
            yScreen = rScreen[1];
        }
Exemple #13
0
        public static void Test()
        {
            double[,] r_screen = new double[3, 3];
            double[][] r_graph = { new double[3], new double[3], new double[3] };


            r_screen[0, 0] = 69;
            r_screen[1, 0] = 68;
            r_screen[2, 0] = 626;
            r_screen[0, 1] = 577;
            r_screen[1, 1] = 84;
            r_screen[2, 1] = 576;
            r_screen[0, 2] = 1;
            r_screen[1, 2] = 1;
            r_screen[2, 2] = 1;

            r_graph[0][0] = 0;
            r_graph[1][0] = 0;
            r_graph[2][0] = 30;
            r_graph[0][1] = -1;
            r_graph[1][1] = 1;
            r_graph[2][1] = -1;
            r_graph[0][2] = 1;
            r_graph[1][2] = 1;
            r_graph[2][2] = 1;

            double[,] s2g = new double[3, 3];
            double[,] g2s = new double[3, 3];

            ScreenToGraph(r_graph, r_screen, s2g, g2s);

            double[] rScreen = new double[3];
            double[] rGraph  = new double[3];

            rScreen[0] = 300;
            rScreen[1] = 300;
            rScreen[2] = 1.0;

            NuGenMath.MatrixMultiply3x1(rGraph, s2g, rScreen);

            double xGraph = rGraph[0];
            double yGraph = rGraph[1];
        }
        //Computes the graph area based on the scale bar definition
        public int ComputeScaleTransformation(CoordSettings coordSettings, NuGenPointSet pointSet)
        {
            double[][] r_graph = { new double[3], new double[3], new double[3] };
            double[,] r_screen = new double[3, 3];

            List <NuGenPoint> points = pointSet.Points;

            scalePointCount = 0;
            validScale      = false;

            foreach (NuGenPoint point in points)
            {
                if (scalePointCount == 2)
                {
                    throw new InvalidOperationException("Can not define more scale bar points");
                }

                if (point.GraphCoordsAreDefined())
                {
                    double xGraph, yGraph;
                    ConvertToCartesian(NuGenMath.mmUnitize(coordSettings), point.XThetaGraph, point.YRGraph,
                                       out xGraph, out yGraph);

                    r_graph[0][scalePointCount] = xGraph;
                    r_graph[1][scalePointCount] = yGraph;
                    r_graph[2][scalePointCount] = 1.0;

                    r_screen[0, scalePointCount] = point.XScreen;
                    r_screen[1, scalePointCount] = point.YScreen;
                    r_screen[2, scalePointCount] = 1.0;

                    scalePointCount++;
                }
            }

            if (scalePointCount == 2)
            {
                // create virtual third point along a virtual axis which is just orthogonal to the virtual
                // axis between the other two points. assumes all points are in same z-value (which is 1.0) plane
                double[] axis1 = new double[3];
                double[] axis2 = new double[3];
                double[] z     = { 0.0, 0.0, 1.0 };

                axis1[0] = r_graph[0][1] - r_graph[0][0];
                axis1[1] = r_graph[1][1] - r_graph[1][0];
                axis1[2] = r_graph[2][1] - r_graph[2][0];

                NuGenMath.VectorCrossProduct(z, axis1, axis2);

                r_graph[0][2] = r_graph[0][0] + axis2[0];
                r_graph[1][2] = r_graph[1][0] + axis2[1];
                r_graph[2][2] = 1.0;

                axis1[0] = r_screen[0, 1] - r_screen[0, 0];
                axis1[1] = r_screen[1, 1] - r_screen[1, 0];
                axis1[2] = r_screen[2, 1] - r_screen[2, 0];

                NuGenMath.VectorCrossProduct(z, axis1, axis2);

                r_screen[0, 2] = r_screen[0, 0] + axis2[0];
                r_screen[1, 2] = r_screen[1, 0] + axis2[1];
                r_screen[2, 2] = 1.0;

                int rtnS2G = NuGenMath.ScreenToGraph(r_graph, r_screen,
                                                     screenToGraph, graphToScreen);

                // log to linear transformation is not allowed when using scale bar since it would
                // be such an extremely rare special case that its benefit would be minimal, especially
                // since it would only confuse the majority of users who would not be expecting it

                validScale = (rtnS2G == NuGenMath.SUCCESS);

                switch (rtnS2G)
                {
                case NuGenMath.SUCCESS:
                    return(NuGenMath.SUCCESS);

                case NuGenMath.BAD_GRAPH_COORDINATES:
                    return(NuGenMath.BAD_GRAPH_COORDINATES);

                case NuGenMath.BAD_SCREEN_COORDINATES:
                    return(NuGenMath.BAD_SCREEN_COORDINATES);
                }
            }

            return(NuGenMath.SUCCESS);
        }
        //Computes the graph area based on the defined axis points, returns a value corresponding
        // to the result of the calculation
        public int ComputeAxesTransformation(CoordSettings coordSettings, NuGenPointSet pointSet)
        {
            double[][] r_graph = { new double[3], new double[3], new double[3] };
            double[,] r_screen = new double[3, 3];

            List <NuGenPoint> points = pointSet.Points;

            axisPointCount = 0;
            validAxes      = false;

            foreach (NuGenPoint p in points)
            {
                if (axisPointCount == 3)
                {
                    throw new InvalidOperationException("We have three axis points, can not compute more");
                }

                if (p.GraphCoordsAreDefined())
                {
                    double xGraph, yGraph;
                    ConvertToCartesian(NuGenMath.mmUnitize(coordSettings), p.XThetaGraph, p.YRGraph, out xGraph, out yGraph);

                    r_graph[0][axisPointCount] = xGraph;
                    r_graph[1][axisPointCount] = yGraph;
                    r_graph[2][axisPointCount] = 1.0;

                    r_screen[0, axisPointCount] = p.XScreen;
                    r_screen[1, axisPointCount] = p.YScreen;
                    r_screen[2, axisPointCount] = 1.0;

                    axisPointCount++;
                }
            }

            if (axisPointCount == 3)
            {
                AdjustMidValuedLogCoords(coordSettings, r_graph);

                int rtnS2G = NuGenMath.ScreenToGraph(r_graph, r_screen, screenToGraph, graphToScreen);

                validAxes = false;

                if (rtnS2G == NuGenMath.SUCCESS)
                {
                    int rtnL2L = ComputeLogToFromLinear(coordSettings, r_graph);

                    switch (rtnL2L)
                    {
                    case NuGenMath.SUCCESS:
                        break;

                    case NuGenMath.NONPOSITIVE_COORDINATE:
                        return(NuGenMath.NONPOSITIVE_COORDINATE);

                    case NuGenMath.NO_SPREAD:
                        return(NuGenMath.NO_SPREAD);
                    }
                }

                validAxes = (rtnS2G == NuGenMath.SUCCESS);

                switch (rtnS2G)
                {
                case NuGenMath.SUCCESS:
                    return(NuGenMath.SUCCESS);

                case NuGenMath.BAD_GRAPH_COORDINATES:
                    return(NuGenMath.BAD_GRAPH_COORDINATES);

                case NuGenMath.BAD_SCREEN_COORDINATES:
                    return(NuGenMath.BAD_SCREEN_COORDINATES);
                }
            }

            return(NuGenMath.SUCCESS);
        }
Exemple #16
0
 private static void TestMatrixInverse()
 {
     NuGenMath.Test();
 }