// // (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 System.Text; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.DB.Structure; using Autodesk.Revit; using System.Drawing; using Point = System.Drawing.Point; namespace Revit.SDK.Samples.NewPathReinforcement.CS { /// /// base class of ProfileFloor and ProfileWall /// contains the profile information and can make matrix to transform point to 2D plane /// public abstract class Profile { #region class member variables /// /// store all the points on the needed face /// protected List> m_points; /// /// object which contains reference to Revit Application /// protected Autodesk.Revit.UI.ExternalCommandData m_commandData; /// /// used to create new instances of utility objects. /// protected Autodesk.Revit.Creation.Application m_appCreator; /// /// Revit DB document /// protected Autodesk.Revit.DB.Document m_document; /// /// store the Matrix used to transform 3D points to 2D /// protected Matrix4 m_to2DMatrix = null; #endregion /// /// CommandData property get object which contains reference to Revit Application /// public Autodesk.Revit.UI.ExternalCommandData CommandData { get { return m_commandData; } } /// /// To2DMatrix property to get Matrix used to transform 3D points to 2D /// public Matrix4 To2DMatrix { get { return m_to2DMatrix; } } /// /// constructor /// /// object which contains reference to Revit Application protected Profile(ExternalCommandData commandData) { m_commandData = commandData; m_appCreator = m_commandData.Application.Application.Create; m_document = m_commandData.Application.ActiveUIDocument.Document; } /// /// abstract method to create PathReinforcement /// /// new created PathReinforcement /// points used to create PathReinforcement /// used to specify whether new PathReinforcement is Filp public abstract PathReinforcement CreatePathReinforcement(List points, bool flip); /// /// Get points in first face /// /// edges in all faces /// points in first face public abstract List> GetNeedPoints(List> faces); /// /// Get a matrix which can transform points to 2D /// public abstract Matrix4 GetTo2DMatrix(); /// /// draw profile of wall or floor in 2D /// /// form graphic /// pen used to draw line in pictureBox /// Matrix used to transform 3d to 2d /// and make picture in right scale public void Draw2D(Graphics graphics, Pen pen, Matrix4 matrix4) { for (int i = 0; i < m_points.Count; i++) { List points = m_points[i]; for (int j = 0; j < points.Count - 1; j++) { Autodesk.Revit.DB.XYZ point1 = points[j]; Autodesk.Revit.DB.XYZ point2 = points[j + 1]; Vector4 v1 = new Vector4(point1); Vector4 v2 = new Vector4(point2); v1 = matrix4.Transform(v1); v2 = matrix4.Transform(v2); graphics.DrawLine(pen, new Point((int)v1.X, (int)v1.Y), new Point((int)v2.X, (int)v2.Y)); } } } /// /// Get edges of element's profile /// /// selected element /// all the faces in the selected Element public List> GetFaces(Autodesk.Revit.DB.Element elem) { List> faceEdges = new List>(); Options options = m_appCreator.NewGeometryOptions(); options.DetailLevel = ViewDetailLevel.Medium; options.ComputeReferences = true; //make sure references to geometric objects are computed. Autodesk.Revit.DB.GeometryElement geoElem = elem.get_Geometry(options); //GeometryObjectArray gObjects = geoElem.Objects; IEnumerator Objects = geoElem.GetEnumerator(); //get all the edges in the Geometry object //foreach (GeometryObject geo in gObjects) while (Objects.MoveNext()) { GeometryObject geo = Objects.Current; Solid solid = geo as Solid; if (solid != null) { FaceArray faces = solid.Faces; foreach (Face face in faces) { EdgeArrayArray edgeArrarr = face.EdgeLoops; foreach (EdgeArray edgeArr in edgeArrarr) { List edgesList = new List(); foreach (Edge edge in edgeArr) { edgesList.Add(edge); } faceEdges.Add(edgesList); } } } } return faceEdges; } /// /// Get normal of face /// /// edges in a face /// vector stands for normal of the face public Vector4 GetFaceNormal(List face) { Edge eg0 = face[0]; Edge eg1 = face[1]; //get two lines from the face List points = eg0.Tessellate() as List; Autodesk.Revit.DB.XYZ start = points[0]; Autodesk.Revit.DB.XYZ end = points[1]; Vector4 vStart = new Vector4((float)start.X, (float)start.Y, (float)start.Z); Vector4 vEnd = new Vector4((float)end.X, (float)end.Y, (float)end.Z); Vector4 vSub = vEnd - vStart; points = eg1.Tessellate() as List; start = points[0]; end = points[1]; vStart = new Vector4((float)start.X, (float)start.Y, (float)start.Z); vEnd = new Vector4((float)end.X, (float)end.Y, (float)end.Z); Vector4 vSub2 = vEnd - vStart; //get the normal with two lines got from face Vector4 result = vSub.CrossProduct(vSub2); result.Normalize(); return result; } /// /// Get a matrix which can move points to center /// /// matrix used to move point to center of graphics public Matrix4 ToCenterMatrix() { //translate the origin to bound center PointF[] bounds = GetFaceBounds(); PointF min = bounds[0]; PointF max = bounds[1]; PointF center = new PointF((min.X + max.X) / 2, (min.Y + max.Y) / 2); return new Matrix4(new Vector4(center.X, center.Y, 0)); } /// /// Get the bound of a face /// /// points array store the bound of the face public PointF[] GetFaceBounds() { Matrix4 matrix = m_to2DMatrix; Matrix4 inverseMatrix = matrix.Inverse(); float minX = 0, maxX = 0, minY = 0, maxY = 0; bool bFirstPoint = true; //get the max and min point on the face for (int i = 0; i < m_points.Count; i++) { List points = m_points[i]; foreach (Autodesk.Revit.DB.XYZ point in points) { Vector4 v = new Vector4(point); Vector4 v1 = inverseMatrix.Transform(v); if (bFirstPoint) { minX = maxX = v1.X; minY = maxY = v1.Y; bFirstPoint = false; } else { if (v1.X < minX) { minX = v1.X; } else if (v1.X > maxX) { maxX = v1.X; } if (v1.Y < minY) { minY = v1.Y; } else if (v1.Y > maxY) { maxY = v1.Y; } } } } //return an array with max and min value of face PointF[] resultPoints = new PointF[2] { new PointF(minX, minY), new PointF(maxX, maxY) }; return resultPoints; } } }