예제 #1
0
        /// <summary>
        /// Normalizes the points coordinates in the plane defined by the shell, and returns the holes and wall segments coordinates
        /// in this new reference system
        /// </summary>
        /// <param name="s"></param>
        /// <param name="segments"></param>
        /// <returns></returns>
        public static (List <Vertex>, GeoTransform) NormalizeShell(Shell s)
        {
            MWPoint3D X0 = s.Points[0];

            // we choose a point p0 and make sure the origin is part of the plane of the shell
            List <MWPoint3D>         cPoints      = s.Points.Select(p => new MWPoint3D(p.X - X0.X, p.Y - X0.Y, p.Z - X0.Z)).ToList();
            List <List <MWPoint3D> > cHolesPoints = s.Holes.Select(lp => lp.Select(p => new MWPoint3D(p.X - X0.X, p.Y - X0.Y, p.Z - X0.Z)).ToList()).ToList();
            List <List <MWPoint3D> > cSegPoints   = s.IncludedSegments.Select(lp => lp.Select(p => new MWPoint3D(p.X - X0.X, p.Y - X0.Y, p.Z - X0.Z)).ToList()).ToList();
            MWPoint3D p0 = new MWPoint3D(0, 0, 0);

            // we look for 2 points such that p0, p1 and p2 are not aligned
            MWPoint3D p1 = cPoints[1];
            MWPoint3D p2 = cPoints[2];

            for (int i = 2; i < cPoints.Count; i++)
            {
                p2 = cPoints[i];
                double dp = Math.Abs((p2.X - p0.X) * (p1.X - p0.X) + (p2.Y - p0.Y) * (p1.Y - p0.Y) + (p2.Z - p0.Z) * (p1.Z - p0.Z));
                if (dp < Points.Distance3D(p0, p1) * Points.Distance3D(p0, p2) - 1e-4)
                {
                    break;
                }
            }

            // we extract two normal vectors defining the plan of the shell
            MWVector3D v = new MWVector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);

            v = v.Normalised();
            MWVector3D w0 = new MWVector3D(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
            MWVector3D n  = Vectors3D.VectorialProduct(v, w0);

            n = n.Normalised();
            MWVector3D w = Vectors3D.VectorialProduct(v, n);

            w = w.Normalised();

            Matrix <double> P = Matrix <double> .Build.DenseOfRowArrays(new[] { v.X, v.Y, v.Z },
                                                                        new[] { w.X, w.Y, w.Z },
                                                                        new[] { n.X, n.Y, n.Z });

            List <MWPoint2D> newPts = cPoints.Select(p =>
            {
                MWVector3D vp = new MWVector3D(p.X, p.Y, p.Z);
                double x      = Vectors3D.ScalarProduct(vp, v);
                double y      = Vectors3D.ScalarProduct(vp, w);
                double z      = Vectors3D.ScalarProduct(vp, n);
                //Console.WriteLine("z = {0} (should be 0)", z);
                return(new MWPoint2D(x, y));
            }).ToList();

            //List<List<MWPoint2D>> newHolesPts = cHolesPoints.Select(lp => lp.Select(p =>
            //{
            //    MWVector3D vp = new MWVector3D(p.X, p.Y, p.Z);
            //    double x = Vectors3D.ScalarProduct(vp, v);
            //    double y = Vectors3D.ScalarProduct(vp, w);
            //    double z = Vectors3D.ScalarProduct(vp, n);
            //    //Console.WriteLine("z = {0} (should be 0)", z);
            //    return new MWPoint2D(x, y);
            //}).ToList()).ToList();

            //List<List<MWPoint2D>> newSegPts = cSegPoints.Select(lp => lp.Select(p =>
            //{
            //    MWVector3D vp = new MWVector3D(p.X, p.Y, p.Z);
            //    double x = Vectors3D.ScalarProduct(vp, v);
            //    double y = Vectors3D.ScalarProduct(vp, w);
            //    double z = Vectors3D.ScalarProduct(vp, n);
            //    //Console.WriteLine("z = {0} (should be 0)", z);
            //    return new MWPoint2D(x, y);
            //}).ToList()).ToList();

            if (newPts.Any(p => double.IsNaN(p.X)))
            {
                Console.WriteLine("NaN");
            }

            double x0 = newPts.Min(p => p.X);
            double y0 = newPts.Min(p => p.Y);
            double x1 = newPts.Max(p => p.X);
            double y1 = newPts.Max(p => p.Y);

            double l = Math.Max(x1 - x0, y1 - y0);

            GeoTransform trans = new GeoTransform()
            {
                P    = P,
                X0   = X0,
                Xmin = new MWPoint2D(x0, y0),
                Xmax = new MWPoint2D(x1, y1)
            };

            return(newPts.Select(p => new Vertex((p.X - x0) / l, (p.Y - y0) / l)).ToList(),
                   trans
                   );
        }
예제 #2
0
        private (Mesh3, List <List <MWPoint3D> >) meshWall(Shell wall, List <List <MWPoint3D> > existingPts = null)
        {
            // create mesh using Triangle.NET library
            Shell w = wall.Clone();

            // pre addition of points on the contours
            List <MWPoint3D> refinedPts = new List <MWPoint3D>();

            for (int i = 0; i < w.Points.Count; i++)
            {
                int        k   = i == w.Points.Count - 1 ? 0 : i + 1;
                MWPoint3D  p0  = w.Points[i];
                MWPoint3D  p1  = w.Points[k];
                MWVector3D vec = new MWVector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
                vec = vec.Normalised();
                double dist = Points.Distance3D(p0, p1);
                int    n    = Convert.ToInt32(dist / 0.75) + 1;
                double inc  = dist / n;
                refinedPts.Add(p0);
                for (int j = 1; j < n; j++)
                {
                    MWPoint3D ptAdded = new MWPoint3D(p0.X + j * vec.X * inc, p0.Y + j * vec.Y * inc, p0.Z + j * vec.Z * inc);
                    refinedPts.Add(ptAdded);
                }
            }
            w.Points = refinedPts;

            if (existingPts != null)
            {
                List <MWPoint3D> exPts = existingPts.SelectMany(l => l).ToList();
                for (int i = 0; i < exPts.Count; i++)
                {
                    for (int j = 0; j < w.Points.Count; j++)
                    {
                        int k = j == w.Points.Count - 1 ? 0 : j + 1;
                        if (PointIsOnLine(w.Points[j], w.Points[k], exPts[i]))
                        {
                            w.Points.Insert(k, exPts[i]);
                            j = 0;
                        }
                    }
                }
            }
            Polygon pol      = new Polygon();
            var     res      = NormalizeShell(w);
            var     vertices = res.Item1;

            pol.Add(new Contour(res.Item1));
            for (int i = 0; i < vertices.Count; i++)
            {
                int k = i == res.Item1.Count - 1 ? 0 : i + 1;
                if (Math.Sqrt(Math.Pow(vertices[i].X - vertices[k].X, 2) + Math.Pow(vertices[i].Y - vertices[k].Y, 2)) < 0.15)
                {
                    pol.Add(new Segment(vertices[i], vertices[k]), false);
                }
            }
            GeoTransform transform = res.Item2;

            double maxL    = getMaxDim(w);
            double maxarea = 0.1 / maxL;

            Configuration  config = new Configuration();
            QualityOptions qo     = new QualityOptions()
            {
                MinimumAngle = 20,
                MaximumArea  = maxarea,
            };

            Mesh MyMesh = (new GenericMesher()).Triangulate(pol, qo) as Mesh;

            List <Point3> meshPts = deNormalizeMesh(MyMesh.Vertices, wall, transform);

            // extracting the contour edges for future wall and slab meshing
            double xmax = MyMesh.Vertices.Max(p => p.X);
            double xmin = MyMesh.Vertices.Min(p => p.X);
            double ymax = MyMesh.Vertices.Max(p => p.Y);
            double ymin = MyMesh.Vertices.Min(p => p.Y);

            List <List <int> > edgesPtsIdx = MyMesh.Edges.Select(e =>
                                                                 new List <int>()
            {
                MyMesh.Vertices.ToList().IndexOf(MyMesh.Vertices.Single(p => p.ID == e.P0)),
                MyMesh.Vertices.ToList().IndexOf(MyMesh.Vertices.Single(p => p.ID == e.P1))
            }).ToList();


            List <Edge> edges = MyMesh.Edges.ToList();
            List <List <MWPoint3D> > TBEdges = new List <List <MWPoint3D> >();
            List <Vertex>            lv      = MyMesh.Vertices.ToList();

            for (int i = 0; i < edges.Count; i++)
            {
                bool b1 = lv[edgesPtsIdx[i][0]].X == xmin && lv[edgesPtsIdx[i][1]].X == xmin;
                bool b2 = lv[edgesPtsIdx[i][0]].X == xmax && lv[edgesPtsIdx[i][1]].X == xmax;
                bool b3 = lv[edgesPtsIdx[i][0]].Y == ymin && lv[edgesPtsIdx[i][1]].Y == ymin;
                bool b4 = lv[edgesPtsIdx[i][0]].Y == ymax && lv[edgesPtsIdx[i][1]].Y == ymax;
                if (b1 || b2 || b3 || b4)
                {
                    TBEdges.Add(new List <MWPoint3D>()
                    {
                        new MWPoint3D(meshPts[edgesPtsIdx[i][0]].X, meshPts[edgesPtsIdx[i][0]].Y, meshPts[edgesPtsIdx[i][0]].Z),
                        new MWPoint3D(meshPts[edgesPtsIdx[i][1]].X, meshPts[edgesPtsIdx[i][1]].Y, meshPts[edgesPtsIdx[i][1]].Z)
                    });
                }
            }

            return(new Mesh3(meshPts, MyMesh.Triangles.Select(t =>
                                                              new Face3(MyMesh.Vertices.ToList().IndexOf(t.GetVertex(0)),
                                                                        MyMesh.Vertices.ToList().IndexOf(t.GetVertex(1)),
                                                                        MyMesh.Vertices.ToList().IndexOf(t.GetVertex(2)))).ToList()),
                   TBEdges);
        }