//
// (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);
}
}
}