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; }
// 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;*/ }
/// <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!"); }
/// <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))); }
/// <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)); } }
/// <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)); }
/// <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); }
/// <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))); }
/// <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)); }
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); }
/// <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); }
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); }
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); }
/// <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; }
/// <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); }
/// <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); }
/// <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)))); }
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); }
/// <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); }
/// <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))); }