// // (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.Drawing.Drawing2D; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB; namespace Revit.SDK.Samples.InPlaceMembers.CS { /// /// trigger when view data updated /// public delegate void UpdateViewDelegate(); /// /// interface as the datasource of view, include nececessary members /// public interface IGraphicsData { /// /// 2D lines /// /// List PointCurves(); /// /// view data update /// event UpdateViewDelegate UpdateViewEvent; /// /// region of 3D view data /// RectangleF Region { get; } } /// /// abstract class include general members /// public abstract class GraphicsDataBase:IGraphicsData { /// ///3D max point after transfered /// protected Autodesk.Revit.DB.XYZ m_transferedMax; /// ///3D min point after transfered /// protected Autodesk.Revit.DB.XYZ m_transferedMin; /// /// origin max define /// protected Autodesk.Revit.DB.XYZ m_originMax = new Autodesk.Revit.DB.XYZ (double.MinValue, double.MinValue, double.MinValue); /// /// origin min define /// protected Autodesk.Revit.DB.XYZ m_originMin = new Autodesk.Revit.DB.XYZ (double.MaxValue, double.MaxValue, double.MaxValue); /// /// origin define /// protected double[,] m_origin = {{ 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }; /// ///minimum value of the region box's edge /// public const float MINEDGElENGTH = 1.0f; /// /// default angle when rotate around X,Y,Z axis /// public const double ROTATEANGLE = System.Math.PI / 90; /// /// update view event /// public virtual event UpdateViewDelegate UpdateViewEvent; /// /// constructor /// public GraphicsDataBase() { Initialize(); } /// /// initialize some member data /// protected void Initialize() { double INITANGLE = Math.PI / 4; RotateX(ref m_origin, INITANGLE); RotateY(ref m_origin, INITANGLE); m_transferedMax = new Autodesk.Revit.DB.XYZ (double.MinValue, double.MinValue, double.MinValue); m_transferedMin = new Autodesk.Revit.DB.XYZ (double.MaxValue, double.MaxValue, double.MaxValue); } /// /// trigger updata view event /// public virtual void UpdataData() { UpdateViewEvent(); } /// /// point curves function /// /// the points list of curves public abstract List PointCurves(); /// /// rectangular region of 3D view data /// public RectangleF Region { get { float width = (float)(m_transferedMax.X - m_transferedMin.X); float height = (float)(m_transferedMax.Y - m_transferedMin.Y); float maxX = (width / 2); float maxY = (height / 2); float minX = -(width / 2); float minY = -(height / 2); if (width < 1) { width = 1; } if (height < 1) { height = 1; } RectangleF rec = new RectangleF(minX, minY, width, height); return rec; } } /// /// rotate around Z axis with default angle /// /// minus or positive angle public void RotateZ(bool direction) { double angle = ROTATEANGLE; if (!direction) { angle = -ROTATEANGLE; } RotateZ(ref m_origin, angle); UpdataData(); } /// /// rotate 3*3 matrix around Z axis /// /// matrix to rotate /// private void RotateZ(ref double[,] origin, double angle) { double sin = Math.Sin(angle); double cos = Math.Cos(angle); double[,] rotate = { { cos, sin, 0.0 }, { -sin, cos, 0.0 }, { 0.0, 0.0, 1.0 } }; origin = MatrixArith.MultiCross(m_origin, rotate); } /// /// rotate around Y axis with default angle /// /// minus or positive angle public void RotateY(bool direction) { double angle = ROTATEANGLE; if (!direction) { angle = -ROTATEANGLE; } RotateY(ref m_origin, angle); UpdataData(); } /// /// rotate 3*3 matrix around Y axis /// /// matrix to rotate /// private void RotateY(ref double[,] origin, double angle) { double sin = Math.Sin(angle); double cos = Math.Cos(angle); double[,] rotate = { { cos, 0.0, -sin }, { 0.0, 1.0, 0.0 }, { sin, 0.0, cos } }; origin = MatrixArith.MultiCross(m_origin, rotate); } /// /// rotate around X axis with default angle /// /// minus or positive angle public void RotateX(bool direction) { double angle = ROTATEANGLE; if (!direction) { angle = -ROTATEANGLE; } RotateX(ref m_origin ,angle); UpdataData(); } /// /// rotate 3*3 matrix around X axis /// /// matrix to rotate /// private void RotateX(ref double[,] origin, double angle) { double sin = Math.Sin(angle); double cos = Math.Cos(angle); double[,] rotate = { { 1.0, 0.0, 0.0 }, { 0.0, cos, sin }, { 0.0, -sin, cos } }; origin = MatrixArith.MultiCross(m_origin, rotate); } } /// /// datasource that can bind to PictureBox3D /// public class GraphicsData : GraphicsDataBase { List> m_originCurves; List> m_transferedCurves; List m_curves2D; /// /// update view event /// public override event UpdateViewDelegate UpdateViewEvent; /// /// constructor to initialize member data /// public GraphicsData() : base() { m_originCurves = new List>(); m_transferedCurves = new List>(); m_curves2D = new List(); } /// /// curves array /// /// public override List PointCurves() { return m_curves2D; } /// /// insert curves array into datasource /// /// points compose the curve public void InsertCurve(List points) { m_originCurves.Add(points); foreach (Autodesk.Revit.DB.XYZ point in points) { m_originMin = UpdateMinRange(point); m_originMax = UpdateMaxRange(point); } } /// /// update 3D view data /// public override void UpdataData() { m_transferedMin = TransferRotate(m_originMin); m_transferedMax = TransferRotate(m_originMax); m_transferedCurves.Clear(); m_curves2D.Clear(); foreach (List points in m_originCurves) { SynChroData(points); } if (null != UpdateViewEvent) { UpdateViewEvent(); } } /// /// update 3D view curve data with origin data and transfer matrix /// /// private void SynChroData(List points) { int size = points.Count; PointF[] points2D = new PointF[size]; List transferedPoints = new List(); for(int i = 0; i m_originMax.X ? pnt.X : m_originMax.X, pnt.Y > m_originMax.Y ? pnt.Y : m_originMax.Y, pnt.Z > m_originMax.Z ? pnt.Z : m_originMax.Z); } private XYZ UpdateMinRange(XYZ pnt) { return new XYZ( pnt.X < m_originMin.X ? pnt.X : m_originMin.X, pnt.Y < m_originMin.Y ? pnt.Y : m_originMin.Y, pnt.Z < m_originMin.Z ? pnt.Z : m_originMin.Z); } /// /// rotate points with origion matrix /// /// /// private Autodesk.Revit.DB.XYZ TransferRotate(Autodesk.Revit.DB.XYZ point) { double x = point.X; double y = point.Y; double z = point.Z; return new XYZ( x * m_origin[0, 0] + y * m_origin[0, 1] + z * m_origin[0, 2], x * m_origin[1, 0] + y * m_origin[1, 1] + z * m_origin[1, 2], x * m_origin[2, 0] + y * m_origin[2, 1] + z * m_origin[2, 2]); } /// /// move the point so that the center of the curves in 3D view is origin /// /// points to be moved /// moved result private Autodesk.Revit.DB.XYZ TransferMove(Autodesk.Revit.DB.XYZ point) { //transform the origin of the old coordinate system in the new coordinate system return new XYZ( point.X - (m_transferedMax.X + m_transferedMin.X) / 2, point.Y - (m_transferedMax.Y + m_transferedMin.Y) / 2, point.Z - (m_transferedMax.Z + m_transferedMin.Z) / 2); } } /// /// utility class provide arithmetic of matrix /// public class MatrixArith { /// /// multiply cross two matrix /// /// left matrix /// right matrix /// result matrix public static double[,] MultiCross(double[,] m1, double[,] m2) { double[,] result = new double[3, 3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { result[i, j] += m1[i, k] * m2[k, j]; } } } return result; } } }