// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using Autodesk.Revit; using Autodesk.Revit.DB; using Element = Autodesk.Revit.DB.Element; using GElement = Autodesk.Revit.DB.GeometryElement; namespace Revit.SDK.Samples.ReferencePlane.CS { /// /// A object to help locating with geometry data. /// public class GeoHelper { //Defined the precision. private const double Precision = 0.0001; /// /// Find the bottom face of a face array. /// /// A face array. /// The bottom face of a face array. static public Face GetBottomFace(FaceArray faces) { Face face = null; double elevation = 0; double tempElevation = 0; Mesh mesh = null; foreach (Face f in faces) { if (IsVerticalFace(f)) { // If this is a vertical face, it cannot be a bottom face to a certainty. continue; } tempElevation = 0; mesh = f.Triangulate(); foreach (Autodesk.Revit.DB.XYZ xyz in mesh.Vertices) { tempElevation = tempElevation + xyz.Z; } tempElevation = tempElevation / mesh.Vertices.Count; if (elevation > tempElevation || null == face) { // Update the bottom face to which's elevation is the lowest. face = f; elevation = tempElevation; } } // The bottom face is consider as which's average elevation is the lowest, except vertical // face. return face; } /// /// Find out the three points which made of a plane. /// /// A mesh contains many points. /// Create a new instance of ReferencePlane. /// The free end apply to reference plane. /// A third point needed to define the reference plane. static public void Distribute(Mesh mesh, ref Autodesk.Revit.DB.XYZ startPoint, ref Autodesk.Revit.DB.XYZ endPoint, ref Autodesk.Revit.DB.XYZ thirdPnt) { int count = mesh.Vertices.Count; startPoint = mesh.Vertices[0]; endPoint = mesh.Vertices[(int)(count / 3)]; thirdPnt = mesh.Vertices[(int)(count / 3 * 2)]; } /// /// Calculate the length between two points. /// /// The start point. /// The end point. /// The length between two points. static public double GetLength(Autodesk.Revit.DB.XYZ startPoint, Autodesk.Revit.DB.XYZ endPoint) { return Math.Sqrt(Math.Pow((endPoint.X - startPoint.X), 2) + Math.Pow((endPoint.Y - startPoint.Y), 2) + Math.Pow((endPoint.Z - startPoint.Z), 2)); } /// /// The distance between two value in a same axis. /// /// start value. /// end value. /// The distance between two value. static public double GetDistance(double start, double end) { return Math.Abs(start - end); } /// /// Get the vector between two points. /// /// The start point. /// The end point. /// The vector between two points. static public Autodesk.Revit.DB.XYZ GetVector(Autodesk.Revit.DB.XYZ startPoint, Autodesk.Revit.DB.XYZ endPoint) { return new Autodesk.Revit.DB.XYZ (endPoint.X - startPoint.X, endPoint.Y - startPoint.Y, endPoint.Z - startPoint.Z); } /// /// Determines whether a face is vertical. /// /// The face to be determined. /// Return true if this face is vertical, or else return false. static private bool IsVerticalFace(Face face) { foreach (EdgeArray ea in face.EdgeLoops) { foreach (Edge e in ea) { if (IsVerticalEdge(e)) { return true; } } } return false; } /// /// Determines whether a edge is vertical. /// /// The edge to be determined. /// Return true if this edge is vertical, or else return false. static private bool IsVerticalEdge(Edge edge) { List polyline = edge.Tessellate() as List; Autodesk.Revit.DB.XYZ verticalVct = new Autodesk.Revit.DB.XYZ (0, 0, 1); Autodesk.Revit.DB.XYZ pointBuffer = polyline[0]; for (int i = 1; i < polyline.Count; i = i + 1) { Autodesk.Revit.DB.XYZ temp = polyline[i]; Autodesk.Revit.DB.XYZ vector = GetVector(pointBuffer, temp); if (Equal(vector, verticalVct)) { return true; } else { continue; } } return false; } /// /// Determines whether two vector are equal in x and y axis. /// /// The vector A. /// The vector B. /// Return true if two vector are equals, or else return false. static private bool Equal(Autodesk.Revit.DB.XYZ vectorA, Autodesk.Revit.DB.XYZ vectorB) { bool isNotEqual = (Precision < Math.Abs(vectorA.X - vectorB.X)) || (Precision < Math.Abs(vectorA.Y - vectorB.Y)); return isNotEqual ? false : true; } } }