// // (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 System.Drawing; using System.Windows.Forms; using Autodesk.Revit.DB; using Autodesk.Revit.UI; namespace Revit.SDK.Samples.CurtainWallGrid.CS { /// /// Maintain the matrixes needed by 3D & 2D operations: pan, zoom, 2D->3D, 3D->2D /// public class GridCoordinates { #region Fields // scale the size of the image to let it shown in the canvas private float m_scaleFactor = 0.85f; // the document of this sample private MyDocument m_myDocument; // stores the current GridDrawing data private GridDrawing m_drawing; // stores the client rectangle of the canvas of the curtain grid // will be used in the scale matrix and move-to-center matrix private System.Drawing.Rectangle m_boundary; // stores the midpoint of the client rectangle // will be used in the scale matrix and move-to-center matrix private System.Drawing.Point m_center; // store the Matrix used to transform 3D points to 2D Matrix4 m_to2DMatrix = null; // store the Matrix used to move points to center Matrix4 m_moveToCenterMatrix = null; // store the Matrix used to scale profile fit to pictureBox Matrix4 m_scaleMatrix = null; // store the Matrix used to transform Revit coordinate to window UI Matrix4 m_transformMatrix = null; // store the Matrix used to transform window UI coordinate to Revit Matrix4 m_restoreMatrix = null; // stores the boundary of the curtain grid List m_boundPoints; #endregion #region Properties /// /// stores the GridDrawing data used in the current dialog /// public GridDrawing Drawing { get { return m_drawing; } set { m_drawing = value; } } /// /// store the Matrix used to transform 3D points to 2D /// public Matrix4 To2DMatrix { get { return m_to2DMatrix; } } /// /// store the Matrix used to transform Revit coordinate to window UI /// public Matrix4 TransformMatrix { get { return m_transformMatrix; } } /// /// store the Matrix used to transform window UI coordinate to Revit /// public Matrix4 RestoreMatrix { get { return m_restoreMatrix; } } #endregion #region Constructors /// /// constructor /// /// /// the document of this sample /// /// /// the GridDrawing data used in the dialog /// public GridCoordinates(MyDocument myDoc, GridDrawing drawing) { m_myDocument = myDoc; if (null == drawing) { TaskDialog.Show("Revit", "Error! There's no grid information in the curtain wall."); } m_drawing = drawing; drawing.Coordinates = this; } #endregion #region Public Methods /// /// obtain the matrixes used in this dialog /// public void GetMatrix() { // initialize the class members, obtain the location information of the canvas m_boundary = m_drawing.Boundary; m_center = m_drawing.Center; // Get a matrix which can transform points to 2D m_to2DMatrix = GetTo2DMatrix(); // get the vertexes of the canvas (in Point/PointF format) m_boundPoints = GetBoundsPoints(); // get a matrix which can keep all the points in the center of the canvas m_moveToCenterMatrix = GetMoveToCenterMatrix(); // get a matrix for scaling all the points and lines within the canvas m_scaleMatrix = GetScaleMatrix(); // transform 3D points to 2D m_transformMatrix = Get3DTo2DMatrix(); // transform from 2D to 3D m_restoreMatrix = Get2DTo3DMatrix(); } #endregion #region Private Methods /// /// calculate the matrix used to transform 2D to 3D /// /// /// matrix used to transform 2d points to 3d /// private Matrix4 Get2DTo3DMatrix() { Matrix4 matrix = Matrix4.Multiply( new Matrix4(new Vector4(-m_center.X, -m_center.Y, 0)), m_scaleMatrix.Inverse()); matrix = Matrix4.Multiply( matrix, m_moveToCenterMatrix); return Matrix4.Multiply(matrix, m_to2DMatrix); } /// /// calculate the matrix used to transform 3D to 2D /// /// /// matrix used to transform 3d points to 2d /// private Matrix4 Get3DTo2DMatrix() { Matrix4 result = Matrix4.Multiply( m_to2DMatrix.Inverse(), m_moveToCenterMatrix.Inverse()); result = Matrix4.Multiply(result, m_scaleMatrix); return Matrix4.Multiply(result, new Matrix4(new Vector4(m_center.X, m_center.Y, 0))); } /// /// calculate the matrix used to scale /// /// /// matrix used to scale the to-be-painted image /// private Matrix4 GetScaleMatrix() { float xScale = m_boundary.Width / (m_boundPoints[1].X - m_boundPoints[0].X); float yScale = m_boundary.Height / (m_boundPoints[1].Y - m_boundPoints[0].Y); float factor = xScale <= yScale ? xScale : yScale; return new Matrix4((float)(factor * m_scaleFactor)); } /// /// Get a matrix which can move points to center /// /// /// matrix used to move point to center of canvas /// private Matrix4 GetMoveToCenterMatrix() { //translate the origin to bound center PointF min = m_boundPoints[0]; PointF max = m_boundPoints[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 max and min coordinates of all points /// /// /// points array stores the bounding box of all points /// private List GetBoundsPoints() { Matrix4 matrix = m_to2DMatrix; Matrix4 inverseMatrix = matrix.Inverse(); float minX = 0, maxX = 0, minY = 0, maxY = 0; bool bFirstPoint = true; List resultPoints = new List(); //get the max and min point on the face foreach (Autodesk.Revit.DB.XYZ point in m_drawing.Geometry.GridVertexesXYZ) { 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; } } } resultPoints.Add(new PointF(minX, minY)); resultPoints.Add(new PointF(maxX, maxY)); return resultPoints; } /// /// Get a matrix which can transform points to 2D /// /// /// matrix which can transform points to 2D /// private Matrix4 GetTo2DMatrix() { Autodesk.Revit.DB.XYZ startXYZ = m_myDocument.WallGeometry.StartXYZ; Autodesk.Revit.DB.XYZ endXYZ = m_myDocument.WallGeometry.EndXYZ; XYZ sub = endXYZ - startXYZ; Vector4 xAxis = new Vector4(new Autodesk.Revit.DB.XYZ(sub.X, sub.Y, sub.Z)); xAxis.Normalize(); //because in the windows UI, Y axis is downward Vector4 yAxis = new Vector4(new Autodesk.Revit.DB.XYZ(0, 0, -1)); yAxis.Normalize(); Vector4 zAxis = Vector4.CrossProduct(xAxis, yAxis); zAxis.Normalize(); Vector4 origin = new Vector4(m_drawing.Geometry.GridVertexesXYZ[0]); return new Matrix4(xAxis, yAxis, zAxis, origin); } #endregion } // end of class }