/// <summary>
        /// Execute the algorithm
        /// </summary>
        private Mesh <PositionedVertexBase, EdgeBase, FaceBase> Process()
        {
            var mesh = CreateMesh(); // TODO: This should return the mesh

            // Add a bounding box to the mesh
            var    points            = mesh.Vertices.Select(v => v.Position);
            BBox2D bbox              = BBox2D.FromPoints(points, 1.0);
            PositionedVertexBase bb0 = mesh.Add(new BoundingVertex(new Point2D(bbox.XMin, bbox.YMin)));
            PositionedVertexBase bb1 = mesh.Add(new BoundingVertex(new Point2D(bbox.XMax, bbox.YMin)));
            PositionedVertexBase bb2 = mesh.Add(new BoundingVertex(new Point2D(bbox.XMax, bbox.YMax)));
            PositionedVertexBase bb3 = mesh.Add(new BoundingVertex(new Point2D(bbox.XMin, bbox.YMax)));

            mesh.AddEdge(bb0, bb1, new BoundingEdge());
            mesh.AddEdge(bb1, bb2, new BoundingEdge());
            mesh.AddEdge(bb2, bb3, new BoundingEdge());
            mesh.AddEdge(bb3, bb0, new BoundingEdge());

            // Monotonize the mesh
            var partitioner = new MonotoneYPartitioner <PositionedVertexBase, EdgeBase, FaceBase>(mesh, InsertMonotonizingDiagonal);

            mesh = partitioner.GetResult();
            return(mesh);
        }
Esempio n. 2
0
        static void Main(string[] args)
        {
            Uri            faultProbabilityUri = UriFromArg(args, 0);
            Uri            horizonUri          = UriFromArg(args, 1);
            GeodysseyModel model = new GeodysseyModel();

            LoaderController.Instance.Open(faultProbabilityUri, model);
            IRegularGrid2D pFaultGrid = model[0]; // The first grid

            LoaderController.Instance.Open(horizonUri, model);
            IRegularGrid2D horizon = model[1];    // Horizon grid

            GridImage pFaultImage = new GridImage(pFaultGrid);

            GridImage pFaultImageX = (GridImage)pFaultImage.Clone();

            pFaultImageX.Clear();

            GridImage pFaultImageY = (GridImage)pFaultImage.Clone();

            pFaultImageY.Clear();

            Convolver.GaussianGradient(pFaultImage, pFaultImageX, pFaultImageY, 1.0);

            GridImage pFaultImageXX = (GridImage)pFaultImage.Clone();

            pFaultImageXX.Clear();

            GridImage pFaultImageYY = (GridImage)pFaultImage.Clone();

            pFaultImageYY.Clear();

            GridImage pFaultImageXY = (GridImage)pFaultImage.Clone();

            pFaultImageXY.Clear();


            Convolver.HessianMatrixOfGaussian(pFaultImage, pFaultImageXX, pFaultImageYY, pFaultImageXY, 1.0);

            //GridImage pFaultImageBeta = (GridImage) RidgeDetector.PrincipleCurvatureDirection(pFaultImageXX, pFaultImageYY, pFaultImageXY);

            //GridImage pFaultImagePQ = (GridImage) RidgeDetector.LocalLpq(pFaultImageXX, pFaultImageYY, pFaultImageXY, pFaultImageBeta);

            //GridImage pFaultImageP = (GridImage) RidgeDetector.LocalLp(pFaultImageX, pFaultImageY, pFaultImageBeta);
            //GridImage pFaultImageQ = (GridImage) RidgeDetector.LocalLq(pFaultImageX, pFaultImageY, pFaultImageBeta);
            //GridImage pFaultImagePP = (GridImage) RidgeDetector.LocalLpp(pFaultImageXX, pFaultImageYY, pFaultImageXY, pFaultImageBeta);
            //GridImage pFaultImageQQ = (GridImage) RidgeDetector.LocalLqq(pFaultImageXX, pFaultImageYY, pFaultImageXY, pFaultImageBeta);

            Trace.WriteLine("Ridge detector");
            GridImage pFaultImageRidge = (GridImage)RidgeDetector.Detect(pFaultImageX, pFaultImageY, pFaultImageXX, pFaultImageYY, pFaultImageXY);

            IImage <bool> ridge = pFaultImageRidge.CreateBinaryImage(0.0);

            Trace.WriteLine("Pepper filter");
            IImage <bool> filtered = Morphology.PepperFiltering(5, ridge);

            Trace.WriteLine("Closing gaps");
            IImage <bool> closed = Morphology.Closing(filtered);

            Trace.WriteLine("Thinning until convergence");
            IImage <bool> thinned = Morphology.ThinUntilConvergence(closed);

            Trace.WriteLine("Thinning blocks until convergence");
            IImage <bool> blockthinned = Morphology.ThinBlockUntilConvergence(thinned);

            Trace.WriteLine("Filling");
            IImage <bool> filled = Morphology.Fill(blockthinned);

            Trace.WriteLine("Connectivity");
            IImage <int> connectivity = BitImage.Analysis.Connectivity(filled);

            Trace.WriteLine("Connected components");
            IImage <int> components = BitImage.Analysis.ConnectedComponents(filled);

            Trace.WriteLine("Mapping faults");
            FaultNetwork network = FaultNetworkMapper.MapFaultNetwork(filled, horizon);

            Trace.WriteLine("Mapping displacements");
            FaultDisplacementMapper displacementMapper = new FaultDisplacementMapper(network);

            var mesh = displacementMapper.GetResult();

            // Output files of mesh
            Trace.WriteLine("Writing faults");
            string faultSegmentsPath = faultProbabilityUri.LocalPath.Replace(".grd", "_faults.poly");
            string monoSegmentsPath  = faultProbabilityUri.LocalPath.Replace(".grd", "_mono.poly");

            using (StreamWriter faultFile = new StreamWriter(faultSegmentsPath))
                using (StreamWriter monoFile = new StreamWriter(monoSegmentsPath))
                {
                    foreach (EdgeBase edge in mesh.Edges)
                    {
                        StreamWriter file   = edge is FaultEdge ? faultFile : monoFile;
                        Point2D      source = ((PositionedVertexBase)edge.Source).Position;
                        Point2D      target = ((PositionedVertexBase)edge.Target).Position;
                        file.WriteLine("{0}\t{1}", source.X, source.Y);
                        file.WriteLine("{0}\t{1}", target.X, target.Y);
                        file.WriteLine("%");
                    }
                }

            // Establish order in the mesh
            Trace.WriteLine("Build planar subdivision - Ordering mesh and inserting faces");
            var orderer     = new Orderer2D <PositionedVertexBase, EdgeBase, FaceBase>(mesh);
            var orderedMesh = orderer.GetResult();

            Debug.Assert(orderedMesh.Euler == 2);

            // Triangulate the mesh
            // Copy the list of monotone faces, so we can iterate over it it
            // whilst modifying the faces in the mesh during triangulation.
            Trace.WriteLine("Triangulating");
            List <FaceBase> faces = new List <FaceBase>(orderedMesh.Faces);

            foreach (FaceBase face in faces)
            {
                var triangulator = new MonotonePolygonTriangulator <PositionedVertexBase, EdgeBase, FaceBase>(orderedMesh, face);
                triangulator.GetResult();
            }

            // Improve triangulation quality
            var improver = new TriangulationQualityImprover <PositionedVertexBase, EdgeBase, FaceBase>(mesh); // TODO: Add a flippable critera

            improver.Improve();

            Trace.WriteLine("Writing mesh");
            // Output the mesh
            Random rng       = new Random();
            string facesPath = faultProbabilityUri.LocalPath.Replace(".grd", "_faces.poly");

            using (StreamWriter facesFile = new StreamWriter(facesPath))
            {
                // All faces except the last one...
                foreach (FaceBase face in orderedMesh.Faces.Take(orderedMesh.FaceCount - 1))
                {
                    foreach (VertexBase vertex in face.Vertices)
                    {
                        PositionedVertexBase pos = (PositionedVertexBase)vertex;
                        Point2D point            = pos.Position;
                        facesFile.WriteLine("{0}\t{1}", point.X, point.Y);
                    }
                    int red   = rng.Next(255);
                    int green = rng.Next(255);
                    int blue  = rng.Next(255);
                    facesFile.WriteLine("% -W0/{0}/{1}/{2} -G{0}/{1}/{2}", red, green, blue);
                }
            }

            // Convert images to grids for convenient output

            //GridImage filteredGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < filteredGrid.Width; ++i)
            //{
            //    for (int j = 0; j < filteredGrid.Height; ++j)
            //    {
            //        filteredGrid[i, j] = filtered[i, j] ? 1.0 : 0.0;
            //    }
            //}

            //GridImage closedGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < closedGrid.Width; ++i)
            //{
            //    for (int j = 0; j < closedGrid.Height; ++j)
            //    {
            //        closedGrid[i, j] = closed[i, j] ? 1.0 : 0.0;
            //    }
            //}

            //GridImage thinnedGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < thinnedGrid.Width; ++i)
            //{
            //    for (int j = 0; j < thinnedGrid.Height; ++j)
            //    {
            //        thinnedGrid[i, j] = thinned[i, j] ? 1.0 : 0.0;
            //    }
            //}

            //GridImage blockThinnedGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < blockThinnedGrid.Width; ++i)
            //{
            //    for (int j = 0; j < blockThinnedGrid.Height; ++j)
            //    {
            //        blockThinnedGrid[i, j] = blockthinned[i, j] ? 1.0 : 0.0;
            //    }
            //}

            GridImage filledGrid = (GridImage)pFaultImageRidge.Clone();

            for (int i = 0; i < filledGrid.Width; ++i)
            {
                for (int j = 0; j < filledGrid.Height; ++j)
                {
                    filledGrid[i, j] = filled[i, j] ? 1.0 : 0.0;
                }
            }

            //GridImage connectivityGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < filledGrid.Width; ++i)
            //{
            //    for (int j = 0; j < filledGrid.Height; ++j)
            //    {
            //        connectivityGrid[i, j] = connectivity[i, j];
            //    }
            //}

            //GridImage componentsGrid = (GridImage) pFaultImageRidge.Clone();
            //for (int i = 0; i < componentsGrid.Width; ++i)
            //{
            //    for (int j = 0; j < componentsGrid.Height; ++j)
            //    {
            //        componentsGrid[i, j] = components[i, j];
            //    }
            //}

            //string pathX = faultProbabilityUri.LocalPath.Replace(".", "_x.");
            //string pathY = faultProbabilityUri.LocalPath.Replace(".", "_y.");
            //string pathXX = faultProbabilityUri.LocalPath.Replace(".", "_xx.");
            //string pathYX = faultProbabilityUri.LocalPath.Replace(".", "_yy.");
            //string pathXY = faultProbabilityUri.LocalPath.Replace(".", "_xy.");
            //string pathBeta = faultProbabilityUri.LocalPath.Replace(".", "_beta.");
            //string pathPQ = faultProbabilityUri.LocalPath.Replace(".", "_pq.");
            //string pathP = faultProbabilityUri.LocalPath.Replace(".", "_p.");
            //string pathQ = faultProbabilityUri.LocalPath.Replace(".", "_q.");
            //string pathPP = faultProbabilityUri.LocalPath.Replace(".", "_pp.");
            //string pathQQ = faultProbabilityUri.LocalPath.Replace(".", "_qq.");
            //string pathRidge = faultProbabilityUri.LocalPath.Replace(".", "_ridge.");
            //string pathFiltered = faultProbabilityUri.LocalPath.Replace(".", "_filtered.");
            //string pathClosed = faultProbabilityUri.LocalPath.Replace(".", "_closed.");
            //string pathThinned = faultProbabilityUri.LocalPath.Replace(".", "_thinned.");
            //string pathBlockThinned = faultProbabilityUri.LocalPath.Replace(".", "_blockthinned.");
            string pathFilled = faultProbabilityUri.LocalPath.Replace(".", "_filled.");
            //string pathConnectivity = faultProbabilityUri.LocalPath.Replace(".", "_connectivity.");
            //string pathComponents = faultProbabilityUri.LocalPath.Replace(".", "_components.");
            //string pathFaultLines = faultProbabilityUri.LocalPath.Replace(".grd", "_faults.poly");
            string pathBisectors = faultProbabilityUri.LocalPath.Replace(".grd", "_bisectors.poly");
            string pathLabels    = faultProbabilityUri.LocalPath.Replace(".grd", "_labels.xy");
            string pathStrands   = faultProbabilityUri.LocalPath.Replace(".grd", "_strands.poly");

            //pFaultImageX.Grid.WriteSurfer6BinaryFile(pathX);
            //pFaultImageY.Grid.WriteSurfer6BinaryFile(pathY);
            //pFaultImageXX.Grid.WriteSurfer6BinaryFile(pathXX);
            //pFaultImageYY.Grid.WriteSurfer6BinaryFile(pathXY);
            //pFaultImageXY.Grid.WriteSurfer6BinaryFile(pathXY);
            //pFaultImageBeta.Grid.WriteSurfer6BinaryFile(pathBeta);
            //pFaultImagePQ.Grid.WriteSurfer6BinaryFile(pathPQ);
            //pFaultImageP.Grid.WriteSurfer6BinaryFile(pathP);
            //pFaultImageQ.Grid.WriteSurfer6BinaryFile(pathQ);
            //pFaultImagePP.Grid.WriteSurfer6BinaryFile(pathPP);
            //pFaultImageQQ.Grid.WriteSurfer6BinaryFile(pathQQ);
            //pFaultImageRidge.Grid.WriteSurfer6BinaryFile(pathRidge);
            //filteredGrid.Grid.WriteSurfer6BinaryFile(pathFiltered);
            //closedGrid.Grid.WriteSurfer6BinaryFile(pathClosed);
            //thinnedGrid.Grid.WriteSurfer6BinaryFile(pathThinned);
            //blockThinnedGrid.Grid.WriteSurfer6BinaryFile(pathBlockThinned);
            filledGrid.Grid.WriteSurfer6BinaryFile(pathFilled);
            //connectivityGrid.Grid.WriteSurfer6BinaryFile(pathConnectivity);
            //componentsGrid.Grid.WriteSurfer6BinaryFile(pathComponents);
            //mapper.OutputPolygons(pathFaultLines);
            //displacementMapper.OutputBisectors(pathBisectors);
            //displacementMapper.OutputLabels(pathLabels);
            //displacementMapper.OutputStrands(pathStrands);
        }
 /// <summary>
 /// Used for inserting monotonizing diagonals into the mesh by the monotone partitioning algorithm.
 /// </summary>
 /// <param name="m"></param>
 /// <param name="fromVertex"></param>
 /// <param name="toVertex"></param>
 private static void InsertMonotonizingDiagonal(Mesh <PositionedVertexBase, EdgeBase, FaceBase> m, PositionedVertexBase fromVertex, PositionedVertexBase toVertex)
 {
     m.AddEdge(fromVertex, toVertex, new MonotonizingEdge());
 }