public ConversionOperator(Triangle src, Triangle dest, bool canChangeVertexes = false, bool canReflect = false)
        {
            result = src;
            transformation = new double[3];
            double distanceOld = src.getDistanceTo(dest);

            int n = 180;
            double nearestDistance = distanceOld;
            for (int i = 0; i < n; i++)
            {
                double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                OptimumConversionOperator oco = new OptimumConversionOperator(src.getTransformation(0,0,phi), dest);
                Triangle tmpResult = oco.getOptimumTriangle();
                double distanceNew = dest.getDistanceTo(tmpResult);
                if (distanceNew < nearestDistance)
                {
                    nearestDistance = distanceNew;
                    result = tmpResult;
                    transformation = oco.transformation;
                    transformation[2] += phi;
                }
            }

            if (canReflect)
            {
                Triangle src_change = new Triangle(src.A, src.C, src.B);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.getTransformation(0, 0, phi), dest);
                    Triangle tmpResult = oco.getOptimumTriangle();
                    double distance = dest.getDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance = distance;
                        result = tmpResult;
                        transformation = oco.transformation;
                        transformation[2] += phi;
                    }
                }
            }

            if (canChangeVertexes)
            {
                Triangle src_change = new Triangle(src.B, src.C, src.A);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.getTransformation(0, 0, phi), dest);
                    Triangle tmpResult = oco.getOptimumTriangle();
                    double distance = dest.getDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance = distance;
                        result = tmpResult;
                        transformation = oco.transformation;
                        transformation[2] += phi;
                    }
                }

                if (canReflect)
                {
                    src_change = new Triangle(src.B, src.A, src.C);
                    for (int i = 0; i < n; i++)
                    {
                        double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                        OptimumConversionOperator oco = new OptimumConversionOperator(src_change.getTransformation(0, 0, phi), dest);
                        Triangle tmpResult = oco.getOptimumTriangle();
                        double distance = dest.getDistanceTo(tmpResult);
                        if (nearestDistance == -1 || distance < nearestDistance)
                        {
                            nearestDistance = distance;
                            result = tmpResult;
                            transformation = oco.transformation;
                            transformation[2] += phi;
                        }
                    }
                }
                src_change = new Triangle(src.C, src.A, src.B);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.getTransformation(0, 0, phi), dest);
                    Triangle tmpResult = oco.getOptimumTriangle();
                    double distance = dest.getDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance = distance;
                        result = tmpResult;
                        transformation = oco.transformation;
                        transformation[2] += phi;
                    }
                }

                if (canReflect)
                {
                    src_change = new Triangle(src.C, src.B, src.A);
                    for (int i = 0; i < n; i++)
                    {
                        double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                        OptimumConversionOperator oco = new OptimumConversionOperator(src_change.getTransformation(0, 0, phi), dest);
                        Triangle tmpResult = oco.getOptimumTriangle();
                        double distance = dest.getDistanceTo(tmpResult);
                        if (nearestDistance == -1 || distance < nearestDistance)
                        {
                            nearestDistance = distance;
                            result = tmpResult;
                            transformation = oco.transformation;
                            transformation[2] += phi;
                        }
                    }
                }
            }
        }
        public OptimumConversionBuilder(Triangle src, Triangle dest, bool canChangeVertexes = false, bool canReflect = false)
        {
            SrcTriangle  = src;
            DestTriangle = dest;

            result         = src;
            transformation = new double[3];

            int    n = 90;
            double nearestDistance = src.GetDistanceTo(dest);

            for (int i = 0; i < n; i++)
            {
                double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                OptimumConversionOperator oco = new OptimumConversionOperator(src.GetTransformation(0, 0, phi), dest);
                Triangle tmpResult            = oco.GetOptimumTriangle();
                double   distanceNew          = dest.GetDistanceTo(tmpResult);
                if (distanceNew < nearestDistance)
                {
                    nearestDistance    = distanceNew;
                    result             = tmpResult;
                    transformation     = oco.transformation;
                    transformation[2] += phi;
                }
            }

            if (canReflect)
            {
                Triangle src_change = new Triangle(src.A, src.C, src.B);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.GetTransformation(0, 0, phi), dest);
                    Triangle tmpResult            = oco.GetOptimumTriangle();
                    double   distance             = dest.GetDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance    = distance;
                        result             = tmpResult;
                        transformation     = oco.transformation;
                        transformation[2] += phi;
                    }
                }
            }

            if (canChangeVertexes)
            {
                Triangle src_change = new Triangle(src.B, src.C, src.A);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.GetTransformation(0, 0, phi), dest);
                    Triangle tmpResult            = oco.GetOptimumTriangle();
                    double   distance             = dest.GetDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance    = distance;
                        result             = tmpResult;
                        transformation     = oco.transformation;
                        transformation[2] += phi;
                    }
                }

                if (canReflect)
                {
                    src_change = new Triangle(src.B, src.A, src.C);
                    for (int i = 0; i < n; i++)
                    {
                        double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                        OptimumConversionOperator oco = new OptimumConversionOperator(src_change.GetTransformation(0, 0, phi), dest);
                        Triangle tmpResult            = oco.GetOptimumTriangle();
                        double   distance             = dest.GetDistanceTo(tmpResult);
                        if (nearestDistance == -1 || distance < nearestDistance)
                        {
                            nearestDistance    = distance;
                            result             = tmpResult;
                            transformation     = oco.transformation;
                            transformation[2] += phi;
                        }
                    }
                }
                src_change = new Triangle(src.C, src.A, src.B);
                for (int i = 0; i < n; i++)
                {
                    double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                    OptimumConversionOperator oco = new OptimumConversionOperator(src_change.GetTransformation(0, 0, phi), dest);
                    Triangle tmpResult            = oco.GetOptimumTriangle();
                    double   distance             = dest.GetDistanceTo(tmpResult);
                    if (nearestDistance == -1 || distance < nearestDistance)
                    {
                        nearestDistance    = distance;
                        result             = tmpResult;
                        transformation     = oco.transformation;
                        transformation[2] += phi;
                    }
                }

                if (canReflect)
                {
                    src_change = new Triangle(src.C, src.B, src.A);
                    for (int i = 0; i < n; i++)
                    {
                        double phi = Math.PI * i * 2.0 / n; //(Math.PI / 180) * i * (360 / n);
                        OptimumConversionOperator oco = new OptimumConversionOperator(src_change.GetTransformation(0, 0, phi), dest);
                        Triangle tmpResult            = oco.GetOptimumTriangle();
                        double   distance             = dest.GetDistanceTo(tmpResult);
                        if (nearestDistance == -1 || distance < nearestDistance)
                        {
                            nearestDistance    = distance;
                            result             = tmpResult;
                            transformation     = oco.transformation;
                            transformation[2] += phi;
                        }
                    }
                }

                Distance = nearestDistance;
            }
        }