Ejemplo n.º 1
0
        // Returns true of the points p0 is on the closed line formed by p1 and p2
        // returns false if p0 equals p1 or p2
        private bool PointIsOnLine(MWPoint3D p1, MWPoint3D p2, MWPoint3D p0)
        {
            double tol = 1e-5;

            if (Math.Abs(p0.X - p1.X) < tol && Math.Abs(p0.Y - p1.Y) < tol && Math.Abs(p0.Z - p1.Z) < tol)
            {
                return(false);
            }
            if (Math.Abs(p0.X - p2.X) < tol && Math.Abs(p0.Y - p2.Y) < tol && Math.Abs(p0.Z - p2.Z) < tol)
            {
                return(false);
            }
            MWVector3D v1      = new MWVector3D(p0.X - p1.X, p0.Y - p1.Y, p0.Z - p1.Z);
            MWVector3D v2      = new MWVector3D(p0.X - p2.X, p0.Y - p2.Y, p0.Z - p2.Z);
            MWVector3D vp      = Vectors3D.VectorialProduct(v1, v2);
            bool       aligned = Math.Sqrt(vp.X * vp.X + vp.Y * vp.Y + vp.Z * vp.Z) < 1e-4;

            if (aligned)
            {
                return(Points.Distance3D(p0, p1) + Points.Distance3D(p0, p2) - Points.Distance3D(p1, p2) < 1e-3);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 2
0
        }                                            // we assume the section coordinates are centered on the beam neutral fiber and already oriented

        public Beam(MWPoint3D start, MWPoint3D end, List <MWPoint2D> secPts)
        {
            Start   = start;
            End     = end;
            Section = secPts;
        }
Ejemplo n.º 3
0
        public static List <Point3> deNormalizeMesh(ICollection <Vertex> lv, Shell s, GeoTransform t)
        {
            MWPoint3D p0 = 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 - p0.X, p.Y - p0.Y, p.Z - p0.Z)).ToList();
            //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 (v,w) defining the plan of the shell and a normal n
            //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();

            //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);
            //    return new MWPoint2D(x, y);
            //}).ToList();

            //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(t.Xmax.X - t.Xmin.X, t.Xmax.Y - t.Xmin.Y); // Math.Max(x1 - x0, y1 - y0);

            // from normalized 2D to non-normalized 2D
            List <MWPoint2D> dPoints = lv.Select(p => new MWPoint2D(t.Xmin.X + l * p.X, t.Xmin.Y + l * p.Y)).ToList();

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

            //Matrix<double> A = 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 });
            Matrix <double> Ainv = t.P.Inverse();

            p0 = t.X0; // s.Points[0];
            List <Point3> points3d = dPoints.Select(p =>
            {
                Vector <double> v2D = Vector <double> .Build.DenseOfArray(new[] { p.X, p.Y, 0.0 });
                Vector <double> v3D = Ainv.Multiply(v2D);
                return(new Point3(p0.X + v3D[0], p0.Y + v3D[1], p0.Z + v3D[2]));
            }).ToList();

            return(points3d);
        }
Ejemplo n.º 4
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
                   );
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        public static (List <Cluster>, List <MWPoint3D>) KMeans(List <Column> cols, int Nc0)
        {
            // data
            //List<ClusterLoad> data = cols.SelectMany(c => c.Loads.Select(l => new ClusterLoad(new MWPoint3D(l.MEdx, l.MEdy, l.P), c, "C"+c.Name + " - " + l.Name))).ToList();
            int Nc = Math.Min(cols.Count, Nc0);
            // columns are clustered according to their mean load
            List <ClusterLoad> loadAvg = cols.Select(c => GetAverageLoad(c)).ToList();

            // means and cluster initializations
            List <MWPoint3D>   means    = new List <MWPoint3D>();
            List <Cluster>     clusters = new List <Cluster>();
            Random             r        = new Random();
            List <ClusterLoad> dataTemp = loadAvg.Select(d => d.Clone()).ToList();

            for (int i = 0; i < Nc; i++)
            {
                int n = (int)Math.Truncate(dataTemp.Count * r.NextDouble());
                means.Add(dataTemp[n].Load);
                dataTemp.RemoveAt(n);
                clusters.Add(new Cluster());
            }

            // assignement initialization
            foreach (var p in loadAvg)
            {
                List <double> distances = new List <double>();
                for (int i = 0; i < Nc; i++)
                {
                    distances.Add(Points.Distance3D(p.Load, means[i]));
                }
                int imin = distances.IndexOf(distances.Min());
                clusters[imin].Loads.Add(p);
            }

            int moves = 1;

            while (moves > 0)
            {
                // means update
                for (int i = 0; i < Nc; i++)
                {
                    double x = clusters[i].Loads.Sum(p => p.Load.X) / clusters[i].Loads.Count;
                    double y = clusters[i].Loads.Sum(p => p.Load.Y) / clusters[i].Loads.Count;
                    double z = clusters[i].Loads.Sum(p => p.Load.Z) / clusters[i].Loads.Count;
                    means[i] = new MWPoint3D(x, y, z);

                    // particular case where a cluster has no element
                    if (Double.IsNaN(means[i].X))
                    {
                        means[i] = new MWPoint3D(0, 0, 0);
                    }
                }

                // assignment update
                moves = 0;
                List <Cluster> clustersTemp = new List <Cluster>();
                for (int i = 0; i < Nc; i++)
                {
                    clustersTemp.Add(new Cluster());
                }

                for (int i = 0; i < Nc; i++)
                {
                    for (int k = 0; k < clusters[i].Loads.Count; k++)
                    {
                        List <double> distances = new List <double>();
                        for (int j = 0; j < Nc; j++)
                        {
                            distances.Add(Points.Distance3D(clusters[i].Loads[k].Load, means[j]));
                        }
                        int imin = distances.IndexOf(distances.Min());
                        if (imin != i)
                        {
                            clustersTemp[imin].Loads.Add(clusters[i].Loads[k]);
                            moves++;
                        }
                        else
                        {
                            clustersTemp[i].Loads.Add(clusters[i].Loads[k]);
                        }
                    }
                }
                for (int i = 0; i < Nc; i++)
                {
                    clusters[i] = clustersTemp[i];
                }
            }

            // Distribute columns load into clusters
            List <Cluster> clustersOut = clusters.Select(c => new Cluster()
            {
                Loads = c.Loads.SelectMany(
                    cl => cols.First(col => col.Name == cl.ParentColumnName).Loads.Select(
                        l => new ClusterLoad(new MWPoint3D(l.MEdx, l.MEdy, l.P), cl.ParentColumnName, cl.ParentColumnName + " - " + l.Name))).ToList()
            }).ToList();

            if (!clustersOut.All(c => c.Loads.Count > 0))
            {
                return(KMeans(cols, Nc));
            }
            else
            {
                return(clustersOut, means);
            }
        }
Ejemplo n.º 7
0
 public ClusterLoad(MWPoint3D load, string colName, string name)
 {
     Load             = load;
     ParentColumnName = colName;
     Name             = name;
 }
Ejemplo n.º 8
0
        public static List <List <MWPoint3D> > KMeans(List <MWPoint3D> data, int Nc)
        {
            // data normalization
            double           maxX  = data.Max(p => p.X);
            double           maxY  = data.Max(p => p.Y);
            double           maxZ  = data.Max(p => p.Z);
            List <MWPoint3D> dataN = data.Select(p => p = new MWPoint3D(p.X / maxX, p.Y / maxY, p.Z / maxZ)).ToList();

            // means and cluster initializations
            List <MWPoint3D>         means    = new List <MWPoint3D>();
            List <List <MWPoint3D> > clusters = new List <List <MWPoint3D> >();
            Random r = new Random();

            for (int i = 0; i < Nc; i++)
            {
                int n = (int)Math.Truncate(data.Count * r.NextDouble());
                means.Add(dataN[n]);
                clusters.Add(new List <MWPoint3D>());
            }

            // assignement initialization
            foreach (var p in dataN)
            {
                List <double> distances = new List <double>();
                for (int i = 0; i < Nc; i++)
                {
                    distances.Add(Points.Distance3D(p, means[i]));
                }
                int imin = distances.IndexOf(distances.Min());
                clusters[imin].Add(p);
            }

            int moves = 1;

            while (moves > 0)
            {
                // means update
                for (int i = 0; i < Nc; i++)
                {
                    double x = clusters[i].Sum(p => p.X) / clusters[i].Count;
                    double y = clusters[i].Sum(p => p.Y) / clusters[i].Count;
                    double z = clusters[i].Sum(p => p.Z) / clusters[i].Count;
                    means[i] = new MWPoint3D(x, y, z);
                }

                // assignment update
                moves = 0;
                List <List <MWPoint3D> > clustersTemp = new List <List <MWPoint3D> >();
                for (int i = 0; i < Nc; i++)
                {
                    clustersTemp.Add(new List <MWPoint3D>());
                }

                for (int i = 0; i < Nc; i++)
                {
                    for (int k = 0; k < clusters[i].Count; k++)
                    {
                        List <double> distances = new List <double>();
                        for (int j = 0; j < Nc; j++)
                        {
                            distances.Add(Points.Distance3D(clusters[i][k], means[j]));
                        }
                        int imin = distances.IndexOf(distances.Min());
                        if (imin != i)
                        {
                            clustersTemp[imin].Add(clusters[i][k]);
                            moves++;
                        }
                        else
                        {
                            clustersTemp[i].Add(clusters[i][k]);
                        }
                    }
                }
                for (int i = 0; i < Nc; i++)
                {
                    clusters[i] = clustersTemp[i];
                }
            }

            return(clusters);
        }