예제 #1
0
        public Angle(XYZ targetVec, XYZ xVec, XYZ yVec)
        {
            this.TargetVector = targetVec;
            this.Radian       = this.TargetVector.AngleTo(xVec);
            XYZ assTargetVec = xVec * Math.Cos(Radian) + yVec * Math.Sin(Radian);

            if (GeomUtil.IsSameDirection(assTargetVec, this.TargetVector))
            {
            }
            else if (GeomUtil.IsOppositeDirection(assTargetVec, this.TargetVector))
            {
                this.Radian *= -1;
            }
            else
            {
                this.Radian  = Math.PI - this.Radian;
                assTargetVec = xVec * Math.Cos(Radian) + yVec * Math.Sin(Radian);
                if (GeomUtil.IsSameDirection(assTargetVec, this.TargetVector))
                {
                }
                else if (GeomUtil.IsOppositeDirection(assTargetVec, this.TargetVector))
                {
                    this.Radian *= -1;
                }
                else
                {
                    throw new Exception("Wrong Calculation!");
                }
            }
            this.Degree = this.Radian * 180 / Math.PI;
        }
예제 #2
0
        // This requires more work
        private Quaternion GetDir(int index)
        {
            var dir = -Vector3.left;

            return(GeomUtil.GetQuatFromDir(dir, Vector3.up));

            /*if (index == MaxIndex)
             *  index--;
             *
             * var dir = mVerts[index + 1] - mVerts[index];
             *
             * var quat = Quaternion.LookRotation(dir, Vector3.up);
             * if (dir == Vector3.up)
             * {
             *  quat = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.AngleAxis(90, Vector3.left);
             *  //quat = Quaternion.AngleAxis(-80, Vector3.up) * Quaternion.AngleAxis(90, Vector3.left);
             *  Debug.Log("kdkd");
             * }
             *
             * if (dir == Vector3.down)
             * {
             *  quat = Quaternion.AngleAxis(90, Vector3.up) *
             *          Quaternion.AngleAxis(-90, Vector3.left) * Quaternion.AngleAxis(0, Vector3.forward);
             * }
             * return quat;*/
        }
예제 #3
0
        /// <summary>
        /// Mô phỏng một tọa độ 3d lên hệ trục địa phương của mặt phẳng
        /// </summary>
        /// <param name="plane">Mặt phẳng đang xét</param>
        /// <param name="point">Điểm 3d đang xét</param>
        /// <returns></returns>
        public static UV Evaluate(Plane plane, XYZ point)
        {
            if (!IsPointInPlane(plane, point))
            {
                point = GetProjectPoint(plane, point);
            }
            Plane  planeOx = Plane.CreateByOriginAndBasis(plane.Origin, plane.XVec, plane.Normal);
            Plane  planeOy = Plane.CreateByOriginAndBasis(plane.Origin, plane.YVec, plane.Normal);
            double lenX    = GetSignedDistance(planeOy, point);
            double lenY    = GetSignedDistance(planeOx, point);

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    double tLenX  = lenX * Math.Pow(-1, i + 1);
                    double tLenY  = lenY * Math.Pow(-1, j + 1);
                    XYZ    tPoint = GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(plane.Origin, plane.XVec, tLenX), plane.YVec, tLenY);
                    if (GeomUtil.IsEqual(tPoint, point))
                    {
                        return(new UV(tLenX, tLenY));
                    }
                }
            }
            throw new Exception("Code complier should never be here!");
        }
예제 #4
0
        /// <summary>
        /// Lấy điểm chiếu của một điểm lên mặt phẳng
        /// </summary>
        /// <param name="plane">Mặt phẳng đang xét</param>
        /// <param name="point">Điểm đang xét</param>
        /// <returns></returns>
        public static XYZ GetProjectPoint(Plane plane, XYZ point)
        {
            double d = GetSignedDistance(plane, point);
            XYZ    q = GeomUtil.AddXYZ(point, GeomUtil.MultiplyVector(plane.Normal, d));

            return(IsPointInPlane(plane, q) ? q : GeomUtil.AddXYZ(point, GeomUtil.MultiplyVector(plane.Normal, -d)));
        }
예제 #5
0
        /// <summary>
        /// "Purge" một List<Curve> được lấy từ các cạnh định nghĩa một mặt trong Revit nhưng gặp một số lỗi phần mềm
        /// </summary>
        /// <param name="cs">List<Curve> đang xét</param>
        /// <returns></returns>
        public static List <Curve> Purge(List <Curve> cs)
        {
            bool         check = true;
            List <Curve> cs1   = new List <Curve>();

            for (int i = 0; i < cs.Count; i++)
            {
                double l = (cs[i].GetEndPoint(0) - cs[i].GetEndPoint(1)).GetLength();
                if (!GeomUtil.IsBigger(l, GeomUtil.milimeter2Feet(10)))
                {
                    check = false;
                    if (i == 0)
                    {
                        cs1.Add(Line.CreateBound(cs[i].GetEndPoint(0), cs[i + 1].GetEndPoint(1)));
                        i = i + 1;
                    }
                    else
                    {
                        cs1[cs1.Count - 1] = Line.CreateBound(cs[i - 1].GetEndPoint(0), cs[i].GetEndPoint(1));
                    }
                }
                else
                {
                    cs1.Add(cs[i]);
                }
            }
            if (check)
            {
                return(cs1);
            }
            else
            {
                return(Purge(cs1));
            }
        }
예제 #6
0
 /// <summary>
 /// Lấy mặt phẳng của mặt đang xét với trục Oy
 /// </summary>
 /// <param name="f">Mặt đang xét</param>
 /// <param name="vecY">Trục Oy của mặt phẳng</param>
 /// <returns></returns>
 public static Plane GetPlaneWithBasisY(PlanarFace f, XYZ vecY)
 {
     if (!GeomUtil.IsEqual(GeomUtil.DotMatrix(vecY, f.FaceNormal), 0))
     {
         throw new Exception("VecY is not perpendicular with Normal!");
     }
     return(Plane.CreateByOriginAndBasis(f.Origin, GeomUtil.UnitVector(GeomUtil.CrossMatrix(vecY, f.FaceNormal)), vecY));
 }
예제 #7
0
        /// <summary>
        /// Mô phỏng một tọa độ 2d trên mặt phẳng đang xét thành tọa độ 3d
        /// </summary>
        /// <param name="p">Mặt phẳng đang xét</param>
        /// <param name="point">Điểm 2d đang xét</param>
        /// <returns></returns>
        public static XYZ Evaluate(Plane p, UV point)
        {
            XYZ pnt = p.Origin;

            pnt = GeomUtil.OffsetPoint(pnt, p.XVec, point.U);
            pnt = GeomUtil.OffsetPoint(pnt, p.YVec, point.V);
            return(pnt);
        }
예제 #8
0
 /// <summary>
 /// Lấy khoảng cách từ một điểm đến một đường thẳng
 /// </summary>
 /// <param name="line">Đường thẳng đang xét</param>
 /// <param name="point">Điểm đang xét</param>
 /// <returns></returns>
 public static double GetSignedDistance(Curve line, XYZ point)
 {
     if (IsPointInLineOrExtend(ConvertLine(line), point))
     {
         return(0);
     }
     return(GeomUtil.GetLength(point, GetProjectPoint(line, point)));
 }
예제 #9
0
        /// <summary>
        /// Lấy điểm chiếu của một điểm lên đường thẳng
        /// </summary>
        /// <param name="line">Đường thẳng đang xét</param>
        /// <param name="point">Điểm đang xét</param>
        /// <returns></returns>
        public static XYZ GetProjectPoint(Curve line, XYZ point)
        {
            if (IsPointInLineOrExtend(CheckGeometry.ConvertLine(line), point))
            {
                return(point);
            }
            XYZ   vecL = GeomUtil.SubXYZ(line.GetEndPoint(1), line.GetEndPoint(0));
            XYZ   vecP = GeomUtil.SubXYZ(point, line.GetEndPoint(0));
            Plane p    = Plane.CreateByOriginAndBasis(line.GetEndPoint(0), GeomUtil.UnitVector(vecL), GeomUtil.UnitVector(GeomUtil.CrossMatrix(vecL, vecP)));

            return(GetProjectPoint(p, point));
        }
예제 #10
0
 int IComparer <XYZ> .Compare(XYZ first, XYZ second)
 {
     if (GeomUtil.IsEqual(first.X, second.X))
     {
         if (GeomUtil.IsEqual(first.Y, second.Y))
         {
             return(0); // Equal
         }
         return((first.Y > second.Y) ? 1 : -1);
     }
     return((first.X > second.X) ? 1 : -1);
 }
예제 #11
0
 /// <summary>
 /// Kiểm tra một điểm nằm trên đường thẳng hay không
 /// </summary>
 /// <param name="line">Đường thằng đang xét</param>
 /// <param name="point">Điểm đang xét</param>
 /// <returns></returns>
 public static bool IsPointInLineOrExtend(Line line, XYZ point)
 {
     if (GeomUtil.IsEqual(point, line.GetEndPoint(0)) || GeomUtil.IsEqual(point, line.GetEndPoint(1)))
     {
         return(true);
     }
     if (GeomUtil.IsSameOrOppositeDirection(GeomUtil.SubXYZ(point, line.GetEndPoint(0)), GeomUtil.SubXYZ(point, line.GetEndPoint(1))))
     {
         return(true);
     }
     return(false);
 }
예제 #12
0
        void Generate(Mesh mesh, List <Vector3> dataPoints, bool pointSphere, float pointSize)
        {
            //mesh.Clear();
            var verts     = new List <Vector3>();
            var normals   = new List <Vector3>();
            var tris      = new List <int>();
            var baseIndex = 0;

            var dimx = pointSize * scale;
            var dimy = pointSize * scale;
            var dimz = pointSize * scale;

            for (int i = 0; i < dataPoints.Count; i++)
            {
                var pos = dataPoints[i];
                if (pointSphere)
                {
                    baseIndex = GeomUtil.CreateSpheroid(
                        baseIndex,
                        xySegments,
                        zSegments,
                        dimx, dimz, dimy,
                        pos,
                        Quaternion.identity,
                        verts,
                        normals,
                        tris);
                }
                else
                {
                    baseIndex = GeomUtil.CreateCubic(
                        baseIndex,
                        dimx,
                        dimy,
                        dimz,
                        pos,
                        Quaternion.identity,
                        verts,
                        normals,
                        tris
                        );
                }
            }
            mesh.SetVertices(verts);
            mesh.SetNormals(normals);
            mesh.SetTriangles(tris, 0);
        }
예제 #13
0
 int IComparer <XYZ> .Compare(XYZ first, XYZ second)
 {
     // first compare z coordinate, then y coordiante, at last x coordinate
     if (GeomUtil.IsEqual(first.Z, second.Z))
     {
         if (GeomUtil.IsEqual(first.Y, second.Y))
         {
             if (GeomUtil.IsEqual(first.X, second.X))
             {
                 return(0); // Equal
             }
             return((first.X > second.X) ? 1 : -1);
         }
         return((first.Y > second.Y) ? 1 : -1);
     }
     return((first.Z > second.Z) ? 1 : -1);
 }
예제 #14
0
        /// <summary>
        /// Tạo ra model từ đoạn thẳng đang xét
        /// </summary>
        /// <param name="doc">Document đang xét</param>
        /// <param name="sp">Mặt phẳng làm việc sẽ chứa đoạn thẳng</param>
        /// <param name="c">Đoạn thẳng đang xét</param>
        public static void CreateModelLine(Document doc, SketchPlane sp, Curve c)
        {
            if (sp != null)
            {
                doc.Create.NewModelCurve(c, sp);
                return;
            }
            if (GeomUtil.IsSameOrOppositeDirection(GetDirection(c), XYZ.BasisZ))
            {
                sp = SketchPlane.Create(doc, Plane.CreateByOriginAndBasis(c.GetEndPoint(0), XYZ.BasisZ, XYZ.BasisX));
                CreateModelLine(doc, sp, c);
                return;
            }
            XYZ vecY = GetDirection(c).CrossProduct(XYZ.BasisZ);

            sp = SketchPlane.Create(doc, Plane.CreateByOriginAndBasis(c.GetEndPoint(0), GeomUtil.UnitVector(GetDirection(c)), GeomUtil.UnitVector(vecY)));
            CreateModelLine(doc, sp, c);
            return;
        }
예제 #15
0
        /// <summary>
        /// Tạo và trả về mặt cắt callout cho đối tượng sàn đang xét
        /// </summary>
        /// <param name="doc">Document chứa đối tượng sàn đang xét</param>
        /// <param name="views">List tất cả các view trong mô hình</param>
        /// <param name="level">Tên level chưa đối tượng sàn</param>
        /// <param name="bb">BoundingBox của đối tượng sàn</param>
        /// <param name="viewName">Tên mặt cắt trả về</param>
        /// <param name="offset">Giá trị offset từ biên đối tượng sàn</param>
        /// <returns></returns>
        public static View CreateFloorCallout(Document doc, List <View> views, string level, BoundingBoxXYZ bb, string viewName, double offset)
        {
            ViewFamilyType vft = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))
                                 .Cast <ViewFamilyType>().FirstOrDefault <ViewFamilyType>(x => ViewFamily.FloorPlan == x.ViewFamily);
            XYZ max = GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(bb.Max, XYZ.BasisX, offset), XYZ.BasisY, offset), XYZ.BasisZ, offset);
            XYZ min = GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(bb.Min, -XYZ.BasisX, offset), -XYZ.BasisY, offset), -XYZ.BasisZ, offset);

            bb = new BoundingBoxXYZ {
                Max = max, Min = min
            };
            View   pv    = null;
            string s     = string.Empty;
            bool   check = false;

            foreach (View v in views)
            {
                try
                {
                    s = v.LookupParameter("Associated Level").AsString();
                    if (s == level)
                    {
                        pv = v; check = true; break;
                    }
                }
                catch
                {
                    continue;
                }
            }
            if (!check)
            {
                throw new Exception("Invalid level name!");
            }
            View vs = ViewSection.CreateCallout(doc, pv.Id, vft.Id, min, max);

            vs.CropBox = bb;
            vs.Name    = viewName;
            return(vs);
        }
예제 #16
0
 /// <summary>
 /// Kiểm tra một điểm nằm trên mặt phẳng hay không
 /// </summary>
 /// <param name="plane">Mặt phẳng đang xét</param>
 /// <param name="point">Điểm đang xét</param>
 /// <returns></returns>
 public static bool IsPointInPlane(Plane plane, XYZ point)
 {
     return(GeomUtil.IsEqual(GetSignedDistance(plane, point), 0) ? true : false);
 }
예제 #17
0
 /// <summary>
 /// Láy vector chỉ phương của đường thẳng
 /// </summary>
 /// <param name="c">Đường thẳng đang xét</param>
 /// <returns></returns>
 public static XYZ GetDirection(Curve c)
 {
     return(GeomUtil.UnitVector(GeomUtil.SubXYZ(c.GetEndPoint(1), c.GetEndPoint(0))));
 }
예제 #18
0
        void Generate()
        {
            mMesh.Clear();
            var verts   = new List <Vector3>();
            var normals = new List <Vector3>();
            var tris    = new List <int>();

            int baseIndex = 0;

            float hGridW = gridWidth / 2f;
            float hGridH = gridHeight / 2f;
            float hGridD = gridDepth / 2f;

            var verticals = new List <Vector3> {
                new Vector3(-hGridW + dimx / 2, 0, -hGridD + dimz / 2f),
                new Vector3(-hGridW + dimx / 2f, 0, hGridD - dimz / 2f),
                new Vector3(hGridW - dimy / 2f, 0, hGridD - dimz / 2f),
                new Vector3(hGridW - dimy / 2f, 0, -hGridD + dimz / 2f)
            };

            foreach (var pt in verticals)
            {
                baseIndex = GeomUtil.CreateCubic(baseIndex,
                                                 dimx, gridHeight - 2 * dimy, dimz,
                                                 new Vector3(posx, posy, posz) + pt,
                                                 Quaternion.identity,
                                                 verts,
                                                 normals,
                                                 tris);
            }

            var horizontals = new List <Vector3> {
                new Vector3(0, -hGridH + dimy / 2f, -hGridD + dimz / 2f),
                new Vector3(0, -hGridH + dimy / 2f, hGridD - dimz / 2f),
                new Vector3(0, hGridH - dimy / 2f, hGridD - dimz / 2f),
                new Vector3(0, hGridH - dimy / 2f, -hGridD + dimz / 2f)
            };

            foreach (var pt in horizontals)
            {
                baseIndex = GeomUtil.CreateCubic(baseIndex,
                                                 gridWidth, dimy, dimz,
                                                 new Vector3(posx, posy, posz) + pt,
                                                 Quaternion.identity,
                                                 verts,
                                                 normals,
                                                 tris);
            }

            var depthinals = new List <Vector3> {
                new Vector3(-hGridW + dimx / 2f, -hGridH + dimy / 2f, 0),
                new Vector3(-hGridW + dimx / 2f, hGridH - dimy / 2f, 0),
                new Vector3(hGridW - dimx / 2f, hGridH - dimy / 2f, 0),
                new Vector3(hGridW - dimx / 2f, -hGridH + dimy / 2f, 0)
            };

            foreach (var pt in depthinals)
            {
                baseIndex = GeomUtil.CreateCubic(baseIndex,
                                                 dimx, dimy, gridDepth - 2 * dimz,
                                                 new Vector3(posx, posy, posz) + pt,
                                                 Quaternion.identity,
                                                 verts,
                                                 normals,
                                                 tris);
            }

            mMesh.SetVertices(verts);
            mMesh.SetNormals(normals);
            mMesh.SetTriangles(tris, 0);
        }
예제 #19
0
        /// <summary>
        /// Tạo và trả về mặt cắt cho đối tượng tường đang xét
        /// </summary>
        /// <param name="linkedDoc">Document chứa đối tượng tường đang xét</param>
        /// <param name="doc">Document liên kết</param>
        /// <param name="id">Địa chỉ Id của đối tượng tường đang xét</param>
        /// <param name="viewName">Tên của mặt cắt trả về</param>
        /// <param name="offset">Giá trị offset từ biên đối tượng tường</param>
        /// <returns></returns>
        public static ViewSection CreateWallSection(Document linkedDoc, Document doc, ElementId id, string viewName, double offset)
        {
            Element e = linkedDoc.GetElement(id);

            if (!(e is Wall))
            {
                throw new Exception("Element is not a wall!");
            }
            Wall wall = (Wall)e;
            Line line = (wall.Location as LocationCurve).Curve as Line;

            ViewFamilyType vft = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)).Cast <ViewFamilyType>().FirstOrDefault <ViewFamilyType>(x => ViewFamily.Section == x.ViewFamily);

            XYZ        p1 = line.GetEndPoint(0), p2 = line.GetEndPoint(1);
            List <XYZ> ps = new List <XYZ> {
                p1, p2
            }; ps.Sort(new ZYXComparer());

            p1 = ps[0]; p2 = ps[1];

            BoundingBoxXYZ bb = wall.get_BoundingBox(null);
            double         minZ = bb.Min.Z, maxZ = bb.Max.Z;

            double l = GeomUtil.GetLength(GeomUtil.SubXYZ(p2, p1));
            double h = maxZ - minZ;
            double w = wall.WallType.Width;

            XYZ min = new XYZ(-l / 2 - offset, minZ - offset, -w - offset);
            XYZ max = new XYZ(l / 2 + offset, maxZ + offset, w + offset);

            Transform tf = Transform.Identity;

            tf.Origin = (p1 + p2) / 2;
            tf.BasisX = GeomUtil.UnitVector(p1 - p2);
            tf.BasisY = XYZ.BasisZ;
            tf.BasisZ = GeomUtil.CrossMatrix(tf.BasisX, tf.BasisY);

            BoundingBoxXYZ sectionBox = new BoundingBoxXYZ()
            {
                Transform = tf, Min = min, Max = max
            };
            ViewSection vs = ViewSection.CreateSection(doc, vft.Id, sectionBox);

            XYZ wallDir = GeomUtil.UnitVector(p2 - p1);
            XYZ upDir   = XYZ.BasisZ;
            XYZ viewDir = GeomUtil.CrossMatrix(wallDir, upDir);

            min = GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(p1, -wallDir, offset), -viewDir, offset);
            min = new XYZ(min.X, min.Y, minZ - offset);
            max = GeomUtil.OffsetPoint(GeomUtil.OffsetPoint(p2, wallDir, offset), viewDir, offset);
            max = new XYZ(max.X, max.Y, maxZ + offset);

            tf  = vs.get_BoundingBox(null).Transform.Inverse;
            max = tf.OfPoint(max);
            min = tf.OfPoint(min);
            double maxx = 0, maxy = 0, maxz = 0, minx = 0, miny = 0, minz = 0;

            if (max.Z > min.Z)
            {
                maxz = max.Z;
                minz = min.Z;
            }
            else
            {
                maxz = min.Z;
                minz = max.Z;
            }


            if (Math.Round(max.X, 4) == Math.Round(min.X, 4))
            {
                maxx = max.X;
                minx = minz;
            }
            else if (max.X > min.X)
            {
                maxx = max.X;
                minx = min.X;
            }

            else
            {
                maxx = min.X;
                minx = max.X;
            }

            if (Math.Round(max.Y, 4) == Math.Round(min.Y, 4))
            {
                maxy = max.Y;
                miny = minz;
            }
            else if (max.Y > min.Y)
            {
                maxy = max.Y;
                miny = min.Y;
            }

            else
            {
                maxy = min.Y;
                miny = max.Y;
            }

            BoundingBoxXYZ sectionView = new BoundingBoxXYZ();

            sectionView.Max = new XYZ(maxx, maxy, maxz);
            sectionView.Min = new XYZ(minx, miny, minz);

            vs.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(ElementId.InvalidElementId);

            vs.get_Parameter(BuiltInParameter.VIEWER_BOUND_FAR_CLIPPING).Set(0);

            vs.CropBoxActive  = true;
            vs.CropBoxVisible = true;

            doc.Regenerate();

            vs.CropBox = sectionView;
            vs.Name    = viewName;
            return(vs);
        }
예제 #20
0
        /// <summary>
        /// Lấy khoảng cách từ môt điểm đến một mặt phẳng
        /// </summary>
        /// <param name="plane">Mặt phẳng đang xét</param>
        /// <param name="point">Điểm đang xét</param>
        /// <returns></returns>
        public static double GetSignedDistance(Plane plane, XYZ point)
        {
            XYZ v = point - plane.Origin;

            return(Math.Abs(GeomUtil.DotMatrix(plane.Normal, v)));
        }