// // (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 System.Collections.ObjectModel; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB; namespace Revit.SDK.Samples.ObjectViewer.CS { /// /// trigger when view data updated /// public delegate void UpdateViewDelegate(); /// /// data class for graphics 3D /// public class Graphics3DData { /// /// Chooses the camera direction to the view /// public enum ViewDirections { /// /// top direction /// Top, /// /// front view /// Front, /// /// left view /// Left, /// /// right view /// Right, /// /// bottom view /// Bottom, /// /// back view /// Back, /// /// iso view diection /// IsoMetric } // default angle when rotate around X,Y,Z axis private const double RotateAngle = System.Math.PI / 90; // initial curves data before UCS transform private readonly List> m_iniCurves = new List>(); // curves data after UCS transform private readonly List> m_curves = new List>(); // number of points representing the 3D geometry private readonly int m_numPoints; // BoundingBox of the 3D geometry private BoundingBoxXYZ m_bbox = new BoundingBoxXYZ(); // current UCS private UCS m_currentUCS = new UCS(); /// /// Current UCS used to transform /// public UCS CurrentUCS { get { return m_currentUCS; } set { m_currentUCS = value; UpdateDisplayData(m_currentUCS); if (null != UpdateViewEvent) { UpdateViewEvent(); } } } /// /// Number of points representing the 3D geometry /// public int NumPoints { get { return m_numPoints; } } // 7 UCS according to camera directions in ViewDirections private static readonly UCS[] SpecialUCSs = new UCS[7]; // small angle used to Rotate UCS around X, Y, Z axis private static readonly UCS RotateXUCS; private static readonly UCS RotateAntiXUCS; private static readonly UCS RotateYUCS; private static readonly UCS RotateAntiYUCS; private static readonly UCS RotateZUCS; private static readonly UCS RotateAntiZUCS; /// /// static constructor used to initialize static members /// static Graphics3DData() { // initialize small angle double angle = RotateAngle; double antiAngle = -RotateAngle; double sin = Math.Sin(angle); double cos = Math.Cos(angle); double antiSin = Math.Sin(antiAngle); double antiCos = Math.Cos(antiAngle); // initialize 6 Rotate UCS Vector origin = new Vector(); RotateXUCS = new UCS(origin, new Vector(1.0, 0.0, 0.0), new Vector(0.0, cos, sin)); RotateAntiXUCS = new UCS(origin, new Vector(1.0, 0.0, 0.0), new Vector(0.0, antiCos, antiSin)); RotateYUCS = new UCS(origin, new Vector(cos, 0.0, -sin), new Vector(0.0, 1.0, 0.0)); RotateAntiYUCS = new UCS(origin, new Vector(antiCos, 0.0, -antiSin), new Vector(0.0, 1.0, 0.0)); RotateZUCS = new UCS(origin, new Vector(cos, sin, 0.0), new Vector(-sin, cos, 0.0)); RotateAntiZUCS = new UCS(origin, new Vector(antiCos, antiSin, 0.0), new Vector(-antiSin, antiCos, 0.0)); // initialize 7 special UCS SpecialUCSs[(int)ViewDirections.IsoMetric] = new UCS(origin, new Vector(-0.408248290463863, 0.408248290463863, 0.816496580927726), new Vector(0.707106781186548, 0.707106781186548, 0.0)); SpecialUCSs[(int)ViewDirections.Top] = new UCS(origin, new Vector(1.0, 0.0, 0.0), new Vector(0.0, 1.0, 0.0)); SpecialUCSs[(int)ViewDirections.Front] = new UCS(origin, new Vector(-1.0, 0.0, 0.0), new Vector(0.0, 0.0, 1.0)); SpecialUCSs[(int)ViewDirections.Left] = new UCS(origin, new Vector(0.0, -1.0, 0.0), new Vector(0.0, 0.0, 1.0)); SpecialUCSs[(int)ViewDirections.Right] = new UCS(origin, new Vector(0.0, 1.0, 0.0), new Vector(0.0, 0.0, 1.0)); SpecialUCSs[(int)ViewDirections.Bottom] = new UCS(origin, new Vector(-1.0, 0.0, 0.0), new Vector(0.0, 1.0, 0.0)); SpecialUCSs[(int)ViewDirections.Back] = new UCS(origin, new Vector(1.0, 0.0, 0.0), new Vector(0.0, 0.0, 1.0)); } /// /// view data update /// public event UpdateViewDelegate UpdateViewEvent; /// /// Curves represent the wireframe of the 3D geometry /// public List> ConstCurves { get { return m_curves; } } /// /// BoundingBox of the 3D geometry /// public BoundingBoxXYZ BBox { get { return m_bbox; } } /// /// constructor /// /// curves represent the wireframe of the 3D geometry /// oundingBox of the 3D geometry public Graphics3DData(List> curves, BoundingBoxXYZ bbox) { if (null == bbox) { return; } foreach (UCS ucs in SpecialUCSs) { ucs.Origin = FindBBoxCenter(bbox); } foreach (List pnts in curves) { List vectors = new List(); m_iniCurves.Add(vectors); foreach (Autodesk.Revit.DB.XYZ pnt in pnts) { vectors.Add(new Vector(pnt.X, pnt.Y, pnt.Z)); m_numPoints++; } } SetViewDirection(ViewDirections.IsoMetric); InitializeBBox(bbox); } /// /// change the camera direction to the geometry /// /// camera direction public void SetViewDirection(ViewDirections viewDirection) { m_currentUCS = SpecialUCSs[(int)viewDirection]; UpdateDisplayData(m_currentUCS); } /// /// rotate around Z axis with default angle /// /// minus or positive angle public void RotateZ(bool direction) { if (direction) { m_currentUCS = m_currentUCS + RotateZUCS; UpdateDisplayData(m_currentUCS); } else { m_currentUCS = m_currentUCS + RotateAntiZUCS; UpdateDisplayData(m_currentUCS); } } /// /// rotate around Y axis with default angle /// /// minus or positive angle public void RotateY(bool direction) { if (direction) { m_currentUCS = m_currentUCS + RotateYUCS; UpdateDisplayData(m_currentUCS); } else { m_currentUCS = m_currentUCS + RotateAntiYUCS; UpdateDisplayData(m_currentUCS); } } /// /// rotate around X axis with default angle /// /// minus or positive angle public void RotateX(bool direction) { if (direction) { m_currentUCS = m_currentUCS + RotateXUCS; UpdateDisplayData(m_currentUCS); } else { m_currentUCS = m_currentUCS + RotateAntiXUCS; UpdateDisplayData(m_currentUCS); } } /// /// update data according to current UCS /// /// private void UpdateDisplayData(UCS lc) { m_curves.Clear(); foreach (List iniVectors in m_iniCurves) { List vectors = new List(); m_curves.Add(vectors); for (int i = 0; i < iniVectors.Count; i++) { // transform points to local coordinate system vectors.Add(lc.GC2LC(iniVectors[i])); } } // trigger update view event if (null != UpdateViewEvent) { UpdateViewEvent(); } } /// /// move the BoundingBox to the center of the Coordinate System, /// modify its size to the size of Geometry's BoundingBox /// /// private void InitializeBBox(BoundingBoxXYZ bbox) { Autodesk.Revit.DB.XYZ size = MathUtil.SubXYZ(bbox.Max, bbox.Min); m_bbox.Max = MathUtil.DivideXYZ(size, 2.0); m_bbox.Min = MathUtil.DivideXYZ(size, -2.0); } /// /// find the center of the BoundingBox /// /// BoundingBox /// center Point private Vector FindBBoxCenter(BoundingBoxXYZ bbox) { Autodesk.Revit.DB.XYZ center = MathUtil.DivideXYZ(MathUtil.AddXYZ(bbox.Max, bbox.Min), 2.0); return MathUtil.XYZ2Vector(center); } } }