private static void notifyProgessListenerIfNeeded(RasterBindingProgress progress,
                                                          int startProgressPercent,
                                                          int endProgressPercent,
                                                          ref double completed,
                                                          ref double previousPercent,
                                                          int sourceWidth)
        {
            if (progress == null)
            {
                return;
            }

            completed += ((double)endProgressPercent - (double)startProgressPercent) / sourceWidth;
            if (Math.Truncate(completed) > previousPercent)
            {
                progress((int)Math.Truncate(completed + startProgressPercent));
                previousPercent = Math.Truncate(completed);
            }
        }
Пример #2
0
        /// <summary>
        /// Performs a rubbersheeting transformation of raster.
        /// </summary>
        /// <param name="source">A System.Drawing.Bitmap instance containing the source image</param>
        /// <param name="sourceControlPoints">Control points of source</param>
        /// <param name="destinationControlPoints">Control points on the map</param>
        /// <param name="rectangle">A bounding rectangle defining a bouns of transformed raster</param>
        /// <param name="progress">Defines a method which is called to notify a subscriber about completion state.</param>
        /// <returns>A System.Drawing.Bitmap instance containing the transformed image</returns>
        public static Bitmap BindRaster(Bitmap source, Point[] sourceControlPoints, ICoordinate[] destinationControlPoints, out BoundingRectangle rectangle, RasterBindingProgress progress)
        {
#if DEMO
            throw new NotImplementedException("This method is not implemented in demo version.");
#else
            if (source == null)
                throw new ArgumentNullException("source");

            if (sourceControlPoints.Length != destinationControlPoints.Length)
                throw new ArgumentException("Number of control points of raster and map should be the same.");

            if (sourceControlPoints.Length < 3)
                throw new ArgumentException("Number of control points should not be less than 3");

            if (!checkControlPoints(source.Width, source.Height, sourceControlPoints))
                throw new ArgumentException("At least one source control point is outside raster", "sourceControlPoints");

            ICoordinate[,] warpTransformResult = new ICoordinate[source.Width, source.Height];
            PointF[,] affinneTransformResult = new PointF[source.Width, source.Height];

            // вычисляем результат аффинного преобразования примененного к координатам точек исходного растра
            calculateAffinneTransform(source.Width, source.Height, affinneTransformResult, sourceControlPoints, destinationControlPoints, progress);
            
            ICoordinate[] shifts = new ICoordinate[destinationControlPoints.Length];
            for (int i = 0; i < shifts.Length; i++)
            {
                PointF p = affinneTransformResult[sourceControlPoints[i].X, sourceControlPoints[i].Y];
                shifts[i] = PlanimetryEnvironment.NewCoordinate(destinationControlPoints[i].X - p.X, destinationControlPoints[i].Y - p.Y);
            }

            // вычисляем новые координаты точек исходного растра, полученные в результате "коробления"
            calculateRubberSheetTransform(source.Width, source.Height, affinneTransformResult, warpTransformResult, destinationControlPoints, shifts, progress);

            // вычисляем ограничивающий прямоугольник преобразованного растра
            rectangle = new BoundingRectangle();
            for (int i = 0; i < source.Width; i++)
                for (int j = 0; j < source.Height; j++)
                {
                    if (!double.IsNaN(warpTransformResult[i, j].X) && !double.IsNaN(warpTransformResult[i, j].Y))
                        rectangle.Join(warpTransformResult[i, j]);
                }

            return calcDestRaster(source, rectangle, warpTransformResult, progress);
#endif
        }
Пример #3
0
        private static Bitmap calcDestRaster(Bitmap source, BoundingRectangle rectangle, ICoordinate[,] warpTransformResult, RasterBindingProgress progress)
        {
            byte[,] fillCount = new byte[source.Width, source.Height];

            Int16[,] r = new Int16[source.Width, source.Height];
            Int16[,] g = new Int16[source.Width, source.Height];
            Int16[,] b = new Int16[source.Width, source.Height];

            for (int i = 0; i < source.Width; i++)
                for (int j = 0; j < source.Height; j++)
                {
                    fillCount[i, j] = 0;
                    r[i, j] = 0;
                    g[i, j] = 0;
                    b[i, j] = 0;
                }

            Bitmap result = new Bitmap(source.Width, source.Height);

            int startProgressPercent = 70;
            int endProgressPercent = 80;
            double completed = 0;
            double previousPercent = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    int x = getDestRasterX(source.Width, warpTransformResult[i, j], rectangle);
                    int y = getDestRasterY(source.Height, warpTransformResult[i, j], rectangle);

                    if (!double.IsNaN(warpTransformResult[i, j].X) && !double.IsNaN(warpTransformResult[i, j].Y) &&
                        x >= 0 && y >= 0)
                    {
                        fillCount[x, y]++;
                        Color c = source.GetPixel(i, j);
                        r[x, y] += c.R;
                        g[x, y] += c.G;
                        b[x, y] += c.B;
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            startProgressPercent = 80;
            endProgressPercent = 90;
            completed = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    int fc = fillCount[i, j];
                    if (fc > 0)
                    {
                        result.SetPixel(i, j,
                            Color.FromArgb(r[i, j] / fc,
                                           g[i, j] / fc,
                                           b[i, j] / fc));
                    }
                    else
                        result.SetPixel(i, j, Color.Transparent);
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            startProgressPercent = 90;
            endProgressPercent = 100;
            completed = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                    if (fillCount[i, j] == 0)
                        fillPixel(i, j, result, fillCount, result.Width, result.Height);

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            return result;
        }
Пример #4
0
        private static void notifyProgessListenerIfNeeded(RasterBindingProgress progress, 
                        int startProgressPercent,
                        int endProgressPercent,
                        ref double completed,
                        ref double previousPercent,
                        int sourceWidth)
        {
            if (progress == null) return;

            completed += ((double)endProgressPercent - (double)startProgressPercent) / sourceWidth;
            if (Math.Truncate(completed) > previousPercent)
            {
                progress((int)Math.Truncate(completed + startProgressPercent));
                previousPercent = Math.Truncate(completed);
            }
        }
Пример #5
0
        private static void calculateAffinneTransform(int width, int height, PointF[,] affinneTransformResult, Point[] sourceNodes, ICoordinate[] destNodes, RasterBindingProgress progress)
        {
            int[] r =
                RasterAlgorithms.calculateOptimalAffineTransformPoints(sourceNodes, destNodes);

            PointF p01 = new PointF(sourceNodes[r[0]].X, sourceNodes[r[0]].Y);
            PointF p02 = new PointF(sourceNodes[r[1]].X, sourceNodes[r[1]].Y);
            PointF p03 = new PointF(sourceNodes[r[2]].X, sourceNodes[r[2]].Y);

            PointF p11 = new PointF((float)destNodes[r[0]].X, (float)destNodes[r[0]].Y);
            PointF p12 = new PointF((float)destNodes[r[1]].X, (float)destNodes[r[1]].Y);
            PointF p13 = new PointF((float)destNodes[r[2]].X, (float)destNodes[r[2]].Y);

            int startProgressPercent = 0;
            int endProgressPercent = 30;
            double completed = 0;
            double previousPercent = 0;

            Matrix m = getAffineTransformMatrix(p01, p02, p03, p11, p12, p13);
            for (int i = 0; i < width; i++)
            {
                PointF[] pts = new PointF[height];
                for (int j = 0; j < height; j++)
                    pts[j] = new PointF(i, j);

                m.TransformPoints(pts);
                for (int j = 0; j < height; j++)
                    affinneTransformResult[i, j] = pts[j];

                if (progress != null)
                {
                    completed += ((double)endProgressPercent - (double)startProgressPercent) / width;
                    if (Math.Truncate(completed) > previousPercent)
                    {
                        progress((int)Math.Truncate(completed + startProgressPercent));
                        previousPercent = Math.Truncate(completed);
                    }
                }
            }
        }
Пример #6
0
        private static void calculateRubberSheetTransform(int width, int height, PointF[,] source, ICoordinate[,] result, ICoordinate[] sourceNodes, ICoordinate[] destNodesShifts, RasterBindingProgress progress)
        {
            double[] w = new double[sourceNodes.Length];
            double[] distances = new double[sourceNodes.Length];

            int startProgressPercent = 30;
            int endProgressPercent = 70;
            double completed = 0;
            double previousPercent = 0;

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    // проверяем попали ли мы в узел интерполяции
                    bool isNode = false;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        if (sourceNodes[k].X == source[i, j].X && 
                            sourceNodes[k].Y == source[i, j].Y)
                        {
                            // попали
                            result[i, j] =
                                PlanimetryEnvironment.NewCoordinate(destNodesShifts[k].X + source[i, j].X,
                                    destNodesShifts[k].Y + source[i, j].Y);
                            isNode = true;
                        }
                    }

                    if (isNode) continue;

                    // расчет расстояний до узлов
                    double maxDistance = 0;
                    for (int t = 0; t < sourceNodes.Length; t++)
                    {
                        ICoordinate p = PlanimetryEnvironment.NewCoordinate(sourceNodes[t].X, sourceNodes[t].Y);
                        distances[t] = PlanimetryAlgorithms.Distance(p,
                                PlanimetryEnvironment.NewCoordinate(source[i, j].X, 
                                           source[i, j].Y));

                        if (maxDistance < distances[t])
                            maxDistance = distances[t];
                    }

                    // расчет знаменателей весов узловых точек
                    double sum = 0;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        sum += Math.Pow(temp, 2);
                    }

                    // расчет весов узловых точек
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        w[k] = Math.Pow(temp, 2) / sum;
                    }

                    // расчет значений новых координат
                    result[i, j] = PlanimetryEnvironment.NewCoordinate(source[i, j].X, source[i, j].Y);
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        result[i, j].X += w[k] * destNodesShifts[k].X;
                        result[i, j].Y += w[k] * destNodesShifts[k].Y;
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, width);
            }
        }
        /// <summary>
        /// Performs a rubbersheeting transformation of raster.
        /// </summary>
        /// <param name="source">A System.Drawing.Bitmap instance containing the source image</param>
        /// <param name="sourceControlPoints">Control points of source</param>
        /// <param name="destinationControlPoints">Control points on the map</param>
        /// <param name="rectangle">A bounding rectangle defining a bouns of transformed raster</param>
        /// <param name="progress">Defines a method which is called to notify a subscriber about completion state.</param>
        /// <returns>A System.Drawing.Bitmap instance containing the transformed image</returns>
        public static Bitmap BindRaster(Bitmap source, Point[] sourceControlPoints, ICoordinate[] destinationControlPoints, out BoundingRectangle rectangle, RasterBindingProgress progress)
        {
#if DEMO
            throw new NotImplementedException("This method is not implemented in demo version.");
#else
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (sourceControlPoints.Length != destinationControlPoints.Length)
            {
                throw new ArgumentException("Number of control points of raster and map should be the same.");
            }

            if (sourceControlPoints.Length < 3)
            {
                throw new ArgumentException("Number of control points should not be less than 3");
            }

            if (!checkControlPoints(source.Width, source.Height, sourceControlPoints))
            {
                throw new ArgumentException("At least one source control point is outside raster", "sourceControlPoints");
            }

            ICoordinate[,] warpTransformResult = new ICoordinate[source.Width, source.Height];
            PointF[,] affinneTransformResult   = new PointF[source.Width, source.Height];

            // вычисляем результат аффинного преобразования примененного к координатам точек исходного растра
            calculateAffinneTransform(source.Width, source.Height, affinneTransformResult, sourceControlPoints, destinationControlPoints, progress);

            ICoordinate[] shifts = new ICoordinate[destinationControlPoints.Length];
            for (int i = 0; i < shifts.Length; i++)
            {
                PointF p = affinneTransformResult[sourceControlPoints[i].X, sourceControlPoints[i].Y];
                shifts[i] = PlanimetryEnvironment.NewCoordinate(destinationControlPoints[i].X - p.X, destinationControlPoints[i].Y - p.Y);
            }

            // вычисляем новые координаты точек исходного растра, полученные в результате "коробления"
            calculateRubberSheetTransform(source.Width, source.Height, affinneTransformResult, warpTransformResult, destinationControlPoints, shifts, progress);

            // вычисляем ограничивающий прямоугольник преобразованного растра
            rectangle = new BoundingRectangle();
            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    if (!double.IsNaN(warpTransformResult[i, j].X) && !double.IsNaN(warpTransformResult[i, j].Y))
                    {
                        rectangle.Join(warpTransformResult[i, j]);
                    }
                }
            }

            return(calcDestRaster(source, rectangle, warpTransformResult, progress));
#endif
        }
        private static Bitmap calcDestRaster(Bitmap source, BoundingRectangle rectangle, ICoordinate[,] warpTransformResult, RasterBindingProgress progress)
        {
            byte[,] fillCount = new byte[source.Width, source.Height];

            Int16[,] r = new Int16[source.Width, source.Height];
            Int16[,] g = new Int16[source.Width, source.Height];
            Int16[,] b = new Int16[source.Width, source.Height];

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    fillCount[i, j] = 0;
                    r[i, j]         = 0;
                    g[i, j]         = 0;
                    b[i, j]         = 0;
                }
            }

            Bitmap result = new Bitmap(source.Width, source.Height);

            int    startProgressPercent = 70;
            int    endProgressPercent   = 80;
            double completed            = 0;
            double previousPercent      = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    int x = getDestRasterX(source.Width, warpTransformResult[i, j], rectangle);
                    int y = getDestRasterY(source.Height, warpTransformResult[i, j], rectangle);

                    if (!double.IsNaN(warpTransformResult[i, j].X) && !double.IsNaN(warpTransformResult[i, j].Y) &&
                        x >= 0 && y >= 0)
                    {
                        fillCount[x, y]++;
                        Color c = source.GetPixel(i, j);
                        r[x, y] += c.R;
                        g[x, y] += c.G;
                        b[x, y] += c.B;
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            startProgressPercent = 80;
            endProgressPercent   = 90;
            completed            = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    int fc = fillCount[i, j];
                    if (fc > 0)
                    {
                        result.SetPixel(i, j,
                                        Color.FromArgb(r[i, j] / fc,
                                                       g[i, j] / fc,
                                                       b[i, j] / fc));
                    }
                    else
                    {
                        result.SetPixel(i, j, Color.Transparent);
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            startProgressPercent = 90;
            endProgressPercent   = 100;
            completed            = 0;

            for (int i = 0; i < source.Width; i++)
            {
                for (int j = 0; j < source.Height; j++)
                {
                    if (fillCount[i, j] == 0)
                    {
                        fillPixel(i, j, result, fillCount, result.Width, result.Height);
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, source.Width);
            }

            return(result);
        }
        private static void calculateAffinneTransform(int width, int height, PointF[,] affinneTransformResult, Point[] sourceNodes, ICoordinate[] destNodes, RasterBindingProgress progress)
        {
            int[] r =
                RasterAlgorithms.calculateOptimalAffineTransformPoints(sourceNodes, destNodes);

            PointF p01 = new PointF(sourceNodes[r[0]].X, sourceNodes[r[0]].Y);
            PointF p02 = new PointF(sourceNodes[r[1]].X, sourceNodes[r[1]].Y);
            PointF p03 = new PointF(sourceNodes[r[2]].X, sourceNodes[r[2]].Y);

            PointF p11 = new PointF((float)destNodes[r[0]].X, (float)destNodes[r[0]].Y);
            PointF p12 = new PointF((float)destNodes[r[1]].X, (float)destNodes[r[1]].Y);
            PointF p13 = new PointF((float)destNodes[r[2]].X, (float)destNodes[r[2]].Y);

            int    startProgressPercent = 0;
            int    endProgressPercent   = 30;
            double completed            = 0;
            double previousPercent      = 0;

            Matrix m = getAffineTransformMatrix(p01, p02, p03, p11, p12, p13);

            for (int i = 0; i < width; i++)
            {
                PointF[] pts = new PointF[height];
                for (int j = 0; j < height; j++)
                {
                    pts[j] = new PointF(i, j);
                }

                m.TransformPoints(pts);
                for (int j = 0; j < height; j++)
                {
                    affinneTransformResult[i, j] = pts[j];
                }

                if (progress != null)
                {
                    completed += ((double)endProgressPercent - (double)startProgressPercent) / width;
                    if (Math.Truncate(completed) > previousPercent)
                    {
                        progress((int)Math.Truncate(completed + startProgressPercent));
                        previousPercent = Math.Truncate(completed);
                    }
                }
            }
        }
Пример #10
0
        private static void calculateRubberSheetTransform(int width, int height, PointF[,] source, ICoordinate[,] result, ICoordinate[] sourceNodes, ICoordinate[] destNodesShifts, RasterBindingProgress progress)
        {
            double[] w         = new double[sourceNodes.Length];
            double[] distances = new double[sourceNodes.Length];

            int    startProgressPercent = 30;
            int    endProgressPercent   = 70;
            double completed            = 0;
            double previousPercent      = 0;

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    // проверяем попали ли мы в узел интерполяции
                    bool isNode = false;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        if (sourceNodes[k].X == source[i, j].X &&
                            sourceNodes[k].Y == source[i, j].Y)
                        {
                            // попали
                            result[i, j] =
                                PlanimetryEnvironment.NewCoordinate(destNodesShifts[k].X + source[i, j].X,
                                                                    destNodesShifts[k].Y + source[i, j].Y);
                            isNode = true;
                        }
                    }

                    if (isNode)
                    {
                        continue;
                    }

                    // расчет расстояний до узлов
                    double maxDistance = 0;
                    for (int t = 0; t < sourceNodes.Length; t++)
                    {
                        ICoordinate p = PlanimetryEnvironment.NewCoordinate(sourceNodes[t].X, sourceNodes[t].Y);
                        distances[t] = PlanimetryAlgorithms.Distance(p,
                                                                     PlanimetryEnvironment.NewCoordinate(source[i, j].X,
                                                                                                         source[i, j].Y));

                        if (maxDistance < distances[t])
                        {
                            maxDistance = distances[t];
                        }
                    }

                    // расчет знаменателей весов узловых точек
                    double sum = 0;
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        sum += Math.Pow(temp, 2);
                    }

                    // расчет весов узловых точек
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        double temp = (maxDistance - distances[k]) / (maxDistance * distances[k]);
                        w[k] = Math.Pow(temp, 2) / sum;
                    }

                    // расчет значений новых координат
                    result[i, j] = PlanimetryEnvironment.NewCoordinate(source[i, j].X, source[i, j].Y);
                    for (int k = 0; k < sourceNodes.Length; k++)
                    {
                        result[i, j].X += w[k] * destNodesShifts[k].X;
                        result[i, j].Y += w[k] * destNodesShifts[k].Y;
                    }
                }

                notifyProgessListenerIfNeeded(progress, startProgressPercent, endProgressPercent, ref completed, ref previousPercent, width);
            }
        }