应用程序名称:PointCloudEngine
Revit 平台:所有版本
Revit 版本:2012.0
首次发布版本:2012.0
编程语言:C#
技能水平:高级
类别:几何
类型:外部命令
主题:点云引擎示例
摘要:
该示例提供了各种自定义点云引擎的示例。
类:
Autodesk.Revit.DB.PointClouds.IPointCloudAccess
Autodesk.Revit.DB.PointClouds.IPointCloudEngine
Autodesk.Revit.DB.PointClouds.IPointSetIterator
Autodesk.Revit.DB.PointClouds.CloudPoint
Autodesk.Revit.DB.PointClouds.PointCloudFilter
Autodesk.Revit.DB.PointCloudType
Autodesk.Revit.DB.PointCloudInstance
项目文件:
FileBasedPointCloud.cs
PointCloudAccessBase.cs
PointCloudCellStorage.cs
PointCloudEngineSample.cs
PredefinedPointCloud.cs
PredefinedPointCloudEngine.cs
XmlUtils.cs
描述:
1.此示例提供了几个点云引擎的变体。在所有情况下,点云本身由单元格表示:
a.一个单元格是由两个点定义的有界矩形3D空间(在点云坐标系中)。
b.点在沿着单元格的主轴运行的边界线上计算。
c.点可以是规则的或者有一些随机因素。
d.给定单元格中的所有点都被分配相同的颜色。
e.给定点云允许有多个单元格。
2.预定义的点云实现提供了非基于文件的点云示例。在非基于文件的点云中,Revit的用户界面不能创建和管理这些点云。应用程序必须提供创建所需实例的能力。
预定义点云
3.提供了基于文件的点云实现。文件格式是XML的特定格式,在其中指定了每个单元格的边界点、颜色和随机化选项。还可以指定点云的整体比例。XML文件应类似于此:
<PointCloud>
<Scale value="2.5"/>
<Cell>
<LowerLeft X="-30" Y="-30" Z="0" />
<UpperRight X="30" Y="30" Z="200" />
<Color value="#000000" />
<Randomize value="True" />
</Cell>
<Cell>
<LowerLeft X="-30" Y="-10" Z="10" />
<UpperRight X="-29" Y="10" Z="150" />
<Color value="#CC3300" />
<Randomize value="False" />
</Cell>
</PointCloud>
基于文件的点云
4.实现的最复杂部分包含在PointCloudAccessBase.ReadSomePoints()方法中。这提供了IPointCloudAccess.ReadPoints()和IPointSetIterator.ReadPoints()的实现,在其中Revit请求通过给定筛选器的点的缓冲区。这是Revit提供点进行显示、选择、对齐和其他操作的方法。
说明:
1.您可以使用“添加预定义实例”插件命令实例化已定义的点云实例。
2.您可以使用“添加随机实例”插件命令实例化一个随机版本。
3.您可以使用“在转换中添加随机实例”插件命令实例化一个带有非默认转换的实例。
4.您还可以通过以下方式实例化基于文件的点云:
a.从“插入”选项卡中选择“点云”。
b.在文件选取对话框中,将文件类型更改为“点云(* .xml)”。
c.浏览到“sample”目录中的“tower.xml”(或另一个正确构建的XML文件)并选择它。
5.您可以使用“序列化点云(实用程序)”插件命令编写默认的XML文件。该文件将写入C:\ 文件夹中。
源代码
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码
FileBasedPointCloud.cs
//
// (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.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Text;
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// An implementation for a file-based point cloud.
/// </summary>
/// <example>
/// The file format is based upon XML. A sample XML looks like:
/// <code>
/// <PointCloud>
/// <Scale value="2.5"/>
/// <Cell>
/// <LowerLeft X="-30" Y="-30" Z="0" />
/// <UpperRight X="30" Y="30" Z="200" />
/// <Color value="#000000" />
/// <Randomize value="True" />
/// </Cell>
/// <Cell>
/// <LowerLeft X="-30" Y="-10" Z="10" />
/// <UpperRight X="-29" Y="10" Z="150" />
/// <Color value="#CC3300" />
/// <Randomize value="False" />
/// </Cell>
/// </PointCloud>
/// </code>
/// The scale value applies to the entire point cloud. One or more cell values should be supplied,
/// with the coordinates of the opposing corners, a color, and an option whether or not to randomize
/// the generated points.
/// </example>
class FileBasedPointCloud : PointCloudAccessBase, IPointCloudAccess
{
#region Class Member Variables
String m_fileName;
#endregion
#region Class Methods
/// <summary>
/// Constructs a new XML-based point cloud access.
/// </summary>
/// <param name="fileName">The full path to the file.</param>
public FileBasedPointCloud(String fileName)
{
m_fileName = fileName;
Setup();
}
/// <summary>
/// Sets up the file-based point cloud.
/// </summary>
private void Setup()
{
if (File.Exists(m_fileName))
{
StreamReader reader = new StreamReader(m_fileName);
XDocument xmlDoc = XDocument.Load(new XmlTextReader(reader));
reader.Close();
SetupFrom(xmlDoc.Element("PointCloud"));
}
}
#endregion
#region IPointCloudAccess Members
/// <summary>
/// The implementation of IPointCloudAccess.GetName().
/// </summary>
/// <returns>The name (the file name).</returns>
public String GetName()
{
return m_fileName;
}
/// <summary>
/// The implementation of IPointCloudAccess.GetColorEncoding()
/// </summary>
/// <returns>The color encoding.</returns>
public PointCloudColorEncoding GetColorEncoding()
{
return PointCloudColorEncoding.ABGR;
}
/// <summary>
/// The implementation of IPointCloudAccess.CreatePointSetIterator().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="viewId">The view id (unused).</param>
/// <returns>The new iterator.</returns>
public IPointSetIterator CreatePointSetIterator(PointCloudFilter rFilter, ElementId viewId)
{
return new PointCloudAccessBase.PointCloudAccessBaseIterator(this, rFilter);
}
/// <summary>
/// The implementation of IPointCloudAccess.CreatePointSetIterator().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="density">The density.</param>
/// <param name="viewId">The view id (unused).</param>
/// <returns>The new iterator.</returns>
public IPointSetIterator CreatePointSetIterator(PointCloudFilter rFilter, double density, ElementId viewId)
{
throw new NotImplementedException();
}
/// <summary>
/// The implementation of IPointCloudAccess.GetExtent().
/// </summary>
/// <returns>The extents of the point cloud.</returns>
public Outline GetExtent()
{
return GetOutline();
}
/// <summary>
/// The implementation of IPointCloudAccess.GetOffset().
/// </summary>
/// <remarks>This method is not used by Revit and will be removed in a later pre-release build.</remarks>
/// <returns>Zero.</returns>
public XYZ GetOffset()
{
return XYZ.Zero;
}
/// <summary>
/// The implementation of IPointCloudAccess.GetUnitsToFeetConversionFactor().
/// </summary>
/// <returns>The scale.</returns>
public double GetUnitsToFeetConversionFactor()
{
return GetScale();
}
/// <summary>
/// The implementation of IPointCloudAccess.ReadPoints().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="viewId">The view id (unused).</param>
/// <param name="buffer">The point cloud buffer.</param>
/// <param name="nBufferSize">The maximum number of points.</param>
/// <returns>The number of points read.</returns>
public int ReadPoints(PointCloudFilter rFilter, ElementId viewId, IntPtr buffer, int nBufferSize)
{
int read = ReadSomePoints(rFilter, buffer, nBufferSize, 0);
return read;
}
/// <summary>
/// The implementation of IPointCloudAccess.Free().
/// </summary>
public void Free()
{
throw new NotImplementedException();
}
#endregion
}
}
PointCloudAccessBase.cs
//
// (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.Xml.Linq;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// The base class for all IPointCloudAccess implementations in this sample.
/// </summary>
public class PointCloudAccessBase
{
#region Class Member Variables
private double m_scale = 1.0;
private List<PointCloudCellStorage> m_storedCells;
private Outline m_outline = null;
#endregion
#region Class Methods
/// <summary>
/// Constructs a new instance of the base class.
/// </summary>
protected PointCloudAccessBase()
{
m_storedCells = new List<PointCloudCellStorage>();
}
/// <summary>
/// Adds a new cell to the point cloud.
/// </summary>
/// <param name="lowerLeft">The lower left point.</param>
/// <param name="upperRight">The upper right point.</param>
/// <param name="color">The color.</param>
/// <param name="randomize">True to randomize point number and location, false for a regular arrangement of points.</param>
protected void AddCell(XYZ lowerLeft, XYZ upperRight, int color, bool randomize)
{
PointCloudCellStorage storage = new PointCloudCellStorage(lowerLeft, upperRight, color, randomize);
storage.GeneratePoints();
m_storedCells.Add(storage);
AddCellToOutline(storage);
}
/// <summary>
/// Adds a new cell to the point cloud.
/// </summary>
/// <param name="lowerLeft">The lower left point.</param>
/// <param name="upperRight">The upper right point.</param>
/// <param name="color">The color.</param>
protected void AddCell(XYZ lowerLeft, XYZ upperRight, int color)
{
AddCell(lowerLeft, upperRight, color, false);
}
/// <summary>
/// Adds a cell to the stored outline of the point cloud. If the cell boundaries extend beyond the current outline, the outline
/// is adjusted.
/// </summary>
/// <param name="storage"></param>
private void AddCellToOutline(PointCloudCellStorage storage)
{
XYZ lowerLeft = storage.LowerLeft;
XYZ upperRight = storage.UpperRight;
if (m_outline == null)
m_outline = new Outline(lowerLeft, upperRight);
else
{
XYZ minimumPoint = m_outline.MinimumPoint;
m_outline.MinimumPoint = new XYZ(Math.Min(minimumPoint.X, lowerLeft.X),
Math.Min(minimumPoint.Y, lowerLeft.Y),
Math.Min(minimumPoint.Z, lowerLeft.Z));
XYZ maximumPoint = m_outline.MaximumPoint;
m_outline.MaximumPoint = new XYZ(Math.Max(maximumPoint.X, upperRight.X),
Math.Max(maximumPoint.Y, upperRight.Y),
Math.Max(maximumPoint.Z, upperRight.Z));
}
}
/// <summary>
/// Gets the outline calculated from all cells in the point cloud.
/// </summary>
/// <returns></returns>
protected Outline GetOutline()
{
return m_outline;
}
/// <summary>
/// Gets the scale stored for this point cloud.
/// </summary>
/// <returns></returns>
protected double GetScale()
{
return m_scale;
}
/// <summary>
/// Saves the contents of the point cloud into an XML element.
/// </summary>
/// <param name="rootElement">The XML element in which to save the point cloud properties.</param>
public virtual void SerializeObjectData(XElement rootElement)
{
XElement scaleElement = XmlUtils.GetXElement(m_scale, "Scale");
rootElement.Add(scaleElement);
int count = m_storedCells.Count;
for (int i = 0; i < count; i++)
{
XElement cellElement = new XElement("Cell");
m_storedCells[i].SerializeObjectData(cellElement);
rootElement.Add(cellElement);
}
}
/// <summary>
/// The internal implementation for point cloud read requests from Revit.
/// </summary>
/// <remarks>Both IPointCloudAccess.ReadPoints() and IPointSetIterator.ReadPoints() are served by this method.</remarks>
/// <param name="rFilter">The point cloud filter.</param>
/// <param name="buffer">The point cloud buffer.</param>
/// <param name="nBufferSize">The maximum number of points in the buffer.</param>
/// <param name="startIndex">The start index for points. Pass 0 if called from IPointCloudAccess.ReadPoints() or if this is the first
/// call to IPointSetIterator.ReadPoints(). Pass the previous cumulative number of read points for second and successive calls to
/// IPointSetIterator.ReadPoints().</param>
/// <returns>The number of points read.</returns>
protected unsafe int ReadSomePoints(PointCloudFilter rFilter, IntPtr buffer, int nBufferSize, int startIndex)
{
// Get the pointer to the buffer.
CloudPoint* cpBuffer = (CloudPoint*)buffer.ToPointer();
int pointIndex = 0;
int currentIndex = startIndex;
int totalPoints = 0;
int startCell = 0;
Outline fullOutline = GetOutline();
// Test each cell until the first cell with needed points is found.
for (int i = 0; i < m_storedCells.Count; i++)
{
PointCloudCellStorage cell = m_storedCells[i];
// Pass the cell outline to the filter.
int filterResult = rFilter.TestCell(cell.LowerLeft, cell.UpperRight);
// Filter result == -1 means the cell is completely out of scope for the filter.
if (filterResult == -1)
continue;
// The cell is at least partially in scope. If the cell has more points than
// the number read in previous calls, we should start with this cell.
// If it has less points than the number read, the cell was already processed and we
// should move to the next one.
totalPoints += cell.NumberOfPoints;
if (currentIndex < totalPoints)
{
startCell = i;
currentIndex = Math.Max(0, startIndex - totalPoints);
break;
}
}
// Start with the current candidate cell and read cells until there are no more to read.
for (int i = startCell; i < m_storedCells.Count; i++)
{
// Test the cell against the filter.
PointCloudCellStorage cell = m_storedCells[i];
int filterResult = rFilter.TestCell(cell.LowerLeft, cell.UpperRight);
// Filter result == -1 means the cell is entirely out of scope, skip it.
if (filterResult == -1)
continue;
// Filter result == 0 means some part of the cell is in scope.
// Prepare for cell is called to process the cell's points.
if (filterResult == 0)
rFilter.PrepareForCell(fullOutline.MinimumPoint, fullOutline.MaximumPoint, cell.NumberOfPoints);
// Loop through all points in the cell.
for (int j = currentIndex; j < cell.NumberOfPoints; j++)
{
// If we need to test the point for acceptance, use the filter to do so.
// If filter result == 1 the entire cell was in scope, no need to test.
if (filterResult == 0)
{
if (!rFilter.TestPoint(cell.PointsBuffer[j]))
continue;
}
// Add the point to the buffer and increment the counter
*(cpBuffer + pointIndex) = cell.PointsBuffer[j];
pointIndex++;
// Stop when the max number of points is reached
if (pointIndex >= nBufferSize)
{
break;
}
}
// Stop when the max number of points is reached
if (pointIndex >= nBufferSize)
{
break;
}
currentIndex = 0;
}
return pointIndex;
}
/// <summary>
/// Sets up a point cloud from an XML root element.
/// </summary>
/// <param name="rootElement">The root element.</param>
protected void SetupFrom(XElement rootElement)
{
// Read scale, if it exists.
foreach (XElement scaleElement in rootElement.Elements("Scale"))
{
double scale = XmlUtils.GetDouble(scaleElement);
if (scale < 0.0)
{
TaskDialog.Show("Scale error", "The value of scale is not a valid number greater than zero.");
}
else
{
m_scale = scale;
}
}
// Read cells.
m_storedCells = new List<PointCloudCellStorage>();
foreach (XElement cellElement in rootElement.Elements("Cell"))
{
PointCloudCellStorage cell = new PointCloudCellStorage(cellElement);
m_storedCells.Add(cell);
AddCellToOutline(cell);
cell.GeneratePoints();
}
}
#endregion
/// <summary>
/// The implementation for an IPointSetIterator for a file-based or predefined point cloud.
/// </summary>
protected class PointCloudAccessBaseIterator : IPointSetIterator
{
#region Class Member Variables
private PointCloudFilter m_filter;
private int m_currentIndex;
private PointCloudAccessBase m_access;
private bool m_done = false;
#endregion
#region Class Methods
/// <summary>
/// Constructs a new instance of the point cloud iterator.
/// </summary>
/// <param name="access">The access.</param>
/// <param name="filter">The filter used for this iteration.</param>
public PointCloudAccessBaseIterator(PointCloudAccessBase access, PointCloudFilter filter)
{
m_access = access;
m_filter = filter;
m_currentIndex = 0;
}
#endregion
#region IPointSetIterator Members
/// <summary>
/// Implementation of IPointSetIterator.ReadPoints()
/// </summary>
/// <param name="buffer">The point buffer.</param>
/// <param name="nBufferSize">The buffer size.</param>
/// <returns>The number of points read.</returns>
public int ReadPoints(IntPtr buffer, int nBufferSize)
{
if (m_done)
{
return 0;
}
int found = m_access.ReadSomePoints(m_filter, buffer, nBufferSize, m_currentIndex);
m_currentIndex += found;
if (found > nBufferSize)
{
m_done = true;
}
return found;
}
/// <summary>
/// Implementation of IPointSetIterator.Free()
/// </summary>
public void Free()
{
m_done = true;
}
#endregion
}
}
}
PointCloudCellStorage.cs
//
// (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.Xml.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// This class is used to calculate and store points for a given cell.
/// </summary>
public class PointCloudCellStorage
{
#region Class Member Variables
[Flags]
private enum PointDirections
{
PlusX = 1,
MinusX = 2,
PlusY = 4,
MinusY = 8,
PlusZ = 16,
MinusZ = 32
}
private CloudPoint[] m_pointsBuffer;
private int m_numberOfPoints;
private XYZ m_lowerLeft;
private XYZ m_upperRight;
private int m_color;
private bool m_randomize;
private const int s_maxNumberOfPoints = 1000000;
private const float s_delta = 0.1f;
private Random m_random = new Random();
#endregion
#region Class Property
/// <summary>
/// The number of points in the cell.
/// </summary>
public int NumberOfPoints
{
get { return m_numberOfPoints; }
}
/// <summary>
/// The lower left point of the cell.
/// </summary>
public XYZ LowerLeft
{
get { return m_lowerLeft; }
}
/// <summary>
/// The upper right point of the cell.
/// </summary>
public XYZ UpperRight
{
get { return m_upperRight; }
}
/// <summary>
/// The points in the cell.
/// </summary>
public CloudPoint[] PointsBuffer
{
get { return m_pointsBuffer; }
}
#endregion
#region Class Methods
/// <summary>
/// Creates a new instance of a rectangular cell.
/// </summary>
/// <param name="lowerLeft">The lower left point of the cell.</param>
/// <param name="upperRight">The upper right point of the cell.</param>
/// <param name="color">The color used for points in the cell.</param>
/// <param name="randomize">True to apply randomization to the number and location of points, false for a regular arrangement of points.</param>
public PointCloudCellStorage(XYZ lowerLeft, XYZ upperRight, int color, bool randomize)
{
m_lowerLeft = lowerLeft;
m_upperRight = upperRight;
m_color = color;
m_randomize = randomize;
m_pointsBuffer = new CloudPoint[s_maxNumberOfPoints];
m_numberOfPoints = 0;
}
/// <summary>
/// Invokes the calculation for all points in the cell.
/// </summary>
public void GeneratePoints()
{
// X direction lines
float xDistance = (float)(m_upperRight.X - m_lowerLeft.X);
AddLine(m_lowerLeft, XYZ.BasisX, PointDirections.PlusY | PointDirections.PlusZ, xDistance);
AddLine(new XYZ(m_lowerLeft.X, m_lowerLeft.Y, m_upperRight.Z), XYZ.BasisX, PointDirections.PlusY | PointDirections.MinusZ, xDistance);
AddLine(new XYZ(m_lowerLeft.X, m_upperRight.Y, m_lowerLeft.Z), XYZ.BasisX, PointDirections.MinusY | PointDirections.PlusZ, xDistance);
AddLine(new XYZ(m_lowerLeft.X, m_upperRight.Y, m_upperRight.Z), XYZ.BasisX, PointDirections.MinusY | PointDirections.MinusZ, xDistance);
// Y direction lines
float yDistance = (float)(m_upperRight.Y - m_lowerLeft.Y);
AddLine(m_lowerLeft, XYZ.BasisY, PointDirections.PlusX | PointDirections.PlusZ, yDistance);
AddLine(new XYZ(m_lowerLeft.X, m_lowerLeft.Y, m_upperRight.Z), XYZ.BasisY, PointDirections.PlusX | PointDirections.MinusZ, yDistance);
AddLine(new XYZ(m_upperRight.X, m_lowerLeft.Y, m_lowerLeft.Z), XYZ.BasisY, PointDirections.MinusX | PointDirections.PlusZ, yDistance);
AddLine(new XYZ(m_upperRight.X, m_lowerLeft.Y, m_upperRight.Z), XYZ.BasisY, PointDirections.MinusX | PointDirections.MinusZ, yDistance);
// Z direction lines
float zDistance = (float)(m_upperRight.Z - m_lowerLeft.Z);
AddLine(m_lowerLeft, XYZ.BasisZ, PointDirections.PlusX | PointDirections.PlusY, zDistance);
AddLine(new XYZ(m_lowerLeft.X, m_upperRight.Y, m_lowerLeft.Z), XYZ.BasisZ, PointDirections.PlusX | PointDirections.MinusY, zDistance);
AddLine(new XYZ(m_upperRight.X, m_lowerLeft.Y, m_lowerLeft.Z), XYZ.BasisZ, PointDirections.MinusX | PointDirections.PlusY, zDistance);
AddLine(new XYZ(m_upperRight.X, m_upperRight.Y, m_lowerLeft.Z), XYZ.BasisZ, PointDirections.MinusX | PointDirections.MinusY, zDistance);
}
private int AddLine(XYZ startPoint, XYZ direction, PointDirections directions, float distance)
{
float deltaX = 0.0f;
int totalRead = 0;
while (deltaX < distance)
{
AddPoints(startPoint + direction * deltaX, directions);
deltaX += s_delta;
}
return totalRead;
}
private void AddModifiedPoint(XYZ point, XYZ modification, double transverseDelta, int pointNumber)
{
XYZ cloudPointXYZ = point + modification * Math.Pow(transverseDelta * pointNumber, 4.0);
CloudPoint cp = new CloudPoint((float)cloudPointXYZ.X, (float)cloudPointXYZ.Y, (float)cloudPointXYZ.Z, m_color);
m_pointsBuffer[m_numberOfPoints] = cp;
m_numberOfPoints++;
if (m_numberOfPoints == s_maxNumberOfPoints)
{
TaskDialog.Show("Point cloud engine", "A single cell is requiring more than the maximum hardcoded number of points for one cell: " + s_maxNumberOfPoints);
throw new Exception("Reached maximum number of points.");
}
}
private void AddPoints(XYZ point, PointDirections directions)
{
// Two random items: number of points, and delta
int numberOfPoints = 5;
double transverseDelta = 0.1;
if (m_randomize)
{
numberOfPoints = 5 + m_random.Next(10);
transverseDelta = m_random.NextDouble() * 0.1;
}
for (int i = 1; i < numberOfPoints; i++)
{
if ((directions & PointDirections.PlusX) == PointDirections.PlusX)
{
AddModifiedPoint(point, XYZ.BasisX, transverseDelta, i);
}
if ((directions & PointDirections.MinusX) == PointDirections.MinusX)
{
AddModifiedPoint(point, -XYZ.BasisX, transverseDelta, i);
}
if ((directions & PointDirections.PlusY) == PointDirections.PlusY)
{
AddModifiedPoint(point, XYZ.BasisY, transverseDelta, i);
}
if ((directions & PointDirections.MinusY) == PointDirections.MinusY)
{
AddModifiedPoint(point, -XYZ.BasisY, transverseDelta, i);
}
if ((directions & PointDirections.PlusZ) == PointDirections.PlusZ)
{
AddModifiedPoint(point, XYZ.BasisZ, transverseDelta, i);
}
if ((directions & PointDirections.MinusZ) == PointDirections.MinusZ)
{
AddModifiedPoint(point, -XYZ.BasisZ, transverseDelta, i);
}
}
}
/// <summary>
/// Serializes the properties of the cell to an XML element.
/// </summary>
/// <param name="rootElement">The element to which the properties are added as subelements.</param>
public void SerializeObjectData(XElement rootElement)
{
rootElement.Add(XmlUtils.GetXElement(m_lowerLeft, "LowerLeft"));
rootElement.Add(XmlUtils.GetXElement(m_upperRight, "UpperRight"));
rootElement.Add(XmlUtils.GetColorXElement(m_color, "Color"));
rootElement.Add(XmlUtils.GetXElement(m_randomize, "Randomize"));
}
/// <summary>
/// Constructs a new instance of a rectangular cell from an XML element.
/// </summary>
/// <param name="rootElement">The XML element representing the cell.</param>
public PointCloudCellStorage(XElement rootElement)
{
m_lowerLeft = XmlUtils.GetXYZ(rootElement.Element("LowerLeft"));
m_upperRight = XmlUtils.GetXYZ(rootElement.Element("UpperRight"));
m_color = XmlUtils.GetColor(rootElement.Element("Color"));
m_randomize = XmlUtils.GetBoolean(rootElement.Element("Randomize"));
m_pointsBuffer = new CloudPoint[s_maxNumberOfPoints];
m_numberOfPoints = 0;
}
#endregion
}
}
PointCloudEngineSample.cs
//
// (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.IO;
using System.Xml;
using System.Xml.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// ExternalApplication used to register the point cloud engines managed by this sample.
/// </summary>
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class PointCloudTestApplication : IExternalApplication
{
#region IExternalApplication Members
/// <summary>
/// The implementation of IExternalApplication.OnStartup()
/// </summary>
/// <param name="application">The Revit application.</param>
/// <returns>Result.Succeeded</returns>
public Result OnStartup(UIControlledApplication application)
{
try
{
// Register point cloud engines for the sample.
// Predefined engine (non-randomized)
IPointCloudEngine engine = new BasicPointCloudEngine(PointCloudEngineType.Predefined);
PointCloudEngineRegistry.RegisterPointCloudEngine("apipc", engine, false);
// Predefined engine with randomized points at the cell borders
engine = new BasicPointCloudEngine(PointCloudEngineType.RandomizedPoints);
PointCloudEngineRegistry.RegisterPointCloudEngine("apipcr", engine, false);
// XML-based point cloud definition
engine = new BasicPointCloudEngine(PointCloudEngineType.FileBased);
PointCloudEngineRegistry.RegisterPointCloudEngine("xml", engine, true);
// Create user interface for accessing predefined point clouds
RibbonPanel panel = application.CreateRibbonPanel("Point cloud testing");
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
panel.AddItem(new PushButtonData("AddPredefinedInstance",
"Add predefined instance",
assembly.Location,
"Revit.SDK.Samples.CS.PointCloudEngine.AddPredefinedInstanceCommand"));
panel.AddSeparator();
panel.AddItem(new PushButtonData("AddRandomizedInstance",
"Add randomized instance",
assembly.Location,
"Revit.SDK.Samples.CS.PointCloudEngine.AddRandomizedInstanceCommand"));
panel.AddSeparator();
panel.AddItem(new PushButtonData("AddTransformedInstance",
"Add randomized instance\nat transform",
assembly.Location,
"Revit.SDK.Samples.CS.PointCloudEngine.AddTransformedInstanceCommand"));
panel.AddSeparator();
panel.AddItem(new PushButtonData("SerializePointCloud",
"Serialize point cloud (utility)",
assembly.Location,
"Revit.SDK.Samples.CS.PointCloudEngine.SerializePredefinedPointCloud"));
}
catch (Exception e)
{
TaskDialog.Show("Exception from OnStartup", e.ToString());
}
return Result.Succeeded;
}
/// <summary>
/// The implementation of IExternalApplication.OnShutdown()
/// </summary>
/// <param name="application">The Revit application.</param>
/// <returns>Result.Succeeded.</returns>
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
#endregion
}
/// <summary>
/// ExternalCommand to add a predefined point cloud.
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class AddPredefinedInstanceCommand : AddInstanceCommandBase, IExternalCommand
{
#region IExternalCommand Members
/// <summary>
/// The implementation for IExternalCommand.Execute()
/// </summary>
/// <param name="commandData">The Revit command data.</param>
/// <param name="message">The error message (ignored).</param>
/// <param name="elements">The elements to display in the failure dialog (ignored).</param>
/// <returns>Result.Succeeded</returns>
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document doc = commandData.View.Document;
AddInstance(doc, "apipc", "", Transform.Identity);
return Result.Succeeded;
}
#endregion
}
/// <summary>
/// ExternalCommand to a predefined point cloud with randomized points.
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class AddRandomizedInstanceCommand : AddInstanceCommandBase, IExternalCommand
{
#region IExternalCommand Members
/// <summary>
/// The implementation for IExternalCommand.Execute()
/// </summary>
/// <param name="commandData">The Revit command data.</param>
/// <param name="message">The error message (ignored).</param>
/// <param name="elements">The elements to display in the failure dialog (ignored).</param>
/// <returns>Result.Succeeded</returns>
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document doc = commandData.View.Document;
AddInstance(doc, "apipcr", "", Transform.Identity);
return Result.Succeeded;
}
#endregion
}
/// <summary>
/// ExternalCommand to add a predefined point cloud at a non-default transform.
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class AddTransformedInstanceCommand : AddInstanceCommandBase, IExternalCommand
{
#region IExternalCommand Members
/// <summary>
/// The implementation for IExternalCommand.Execute()
/// </summary>
/// <param name="commandData">The Revit command data.</param>
/// <param name="message">The error message (ignored).</param>
/// <param name="elements">The elements to display in the failure dialog (ignored).</param>
/// <returns>Result.Succeeded</returns>
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document doc = commandData.View.Document;
Transform trf = Transform.CreateRotationAtPoint(XYZ.BasisZ, Math.PI / 6.0, new XYZ(10, 5, 0));
AddInstance(doc, "apipcr", "", trf);
return Result.Succeeded;
}
#endregion
}
/// <summary>
/// Base class for ExternalCommands used to add point cloud instances programmatically.
/// </summary>
public class AddInstanceCommandBase
{
/// <summary>
/// Adds a point cloud instance programmatically.
/// </summary>
/// <param name="doc">The document.</param>
/// <param name="engineType">The engine identifier string.</param>
/// <param name="identifier">The identifier for the particular point cloud.</param>
/// <param name="trf">The transform to apply to the new point cloud instance.</param>
public void AddInstance(Document doc, String engineType, String identifier, Transform trf)
{
Transaction t = new Transaction(doc, "Create PC instance");
t.Start();
PointCloudType type = PointCloudType.Create(doc, engineType, identifier);
PointCloudInstance.Create(doc, type.Id, trf);
t.Commit();
}
}
/// <summary>
/// Utility ExternalCommand to take a predefined point cloud and write the corresponding XML for it to disk.
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.ReadOnly)]
public class SerializePredefinedPointCloud : AddInstanceCommandBase, IExternalCommand
{
#region IExternalCommand Members
/// <summary>
/// The implementation for IExternalCommand.Execute()
/// </summary>
/// <param name="commandData">The Revit command data.</param>
/// <param name="message">The error message (ignored).</param>
/// <param name="elements">The elements to display in the failure dialog (ignored).</param>
/// <returns>Result.Succeeded</returns>
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
PredefinedPointCloud cloud = new PredefinedPointCloud("dummy");
XDocument doc = new XDocument();
XElement root = new XElement("PointCloud");
cloud.SerializeObjectData(root);
doc.Add(root);
TextWriter writer = new StreamWriter(@"c:\serializedPC.xml");
doc.WriteTo(new XmlTextWriter(writer));
writer.Close();
return Result.Succeeded;
}
#endregion
}
}
PredefinedPointCloud.cs
//
// (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.IO;
using System.Runtime.Serialization;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// An implementation for a non file-based point cloud. In this implementaiton, the location of the cells, including their colors and options,
/// are hardcoded.
/// </summary>
public class PredefinedPointCloud : PointCloudAccessBase, IPointCloudAccess
{
#region Class Member Variables
String m_identifier;
#endregion
#region Class Methods
/// <summary>
/// Constructs a new predefined point cloud access instance.
/// </summary>
/// <param name="identifier">The identifier of the point cloud.</param>
public PredefinedPointCloud(String identifier)
{
m_identifier = identifier;
Setup(false);
}
/// <summary>
/// Constructs a new predefined point cloud access instance.
/// </summary>
/// <param name="identifier">The identifier of the point cloud.</param>
/// <param name="randomizedPoints">True to use randomization for the point location and number, false otherwise.</param>
public PredefinedPointCloud(String identifier, bool randomizedPoints)
{
m_identifier = identifier;
Setup(randomizedPoints);
}
/// <summary>
/// Sets up the predefined point cloud.
/// </summary>
/// <param name="randomizedPoints">True to use randomization for the point location and number, false otherwise.</param>
private void Setup(bool randomizedPoints)
{
AddCell(new XYZ(0, 0, 0), new XYZ(0.5, 100, 10), 0x00CCCC, randomizedPoints);
AddCell(new XYZ(0, 0, 0), new XYZ(50, 0.5, 10), 0x00CCCC, randomizedPoints);
AddCell(new XYZ(49.5, 0, 0), new XYZ(50, 100, 10), 0x00CCCC, randomizedPoints);
AddCell(new XYZ(0, 99.5, 0), new XYZ(50, 100, 10), 0x00CCCC, randomizedPoints);
AddCell(new XYZ(10, 0, 0), new XYZ(14, 0.5, 7), 0xCC99CC, randomizedPoints);
AddCell(new XYZ(30, 0, 3), new XYZ(33, 0.5, 8), 0xA0A0A0, randomizedPoints);
AddCell(new XYZ(33, 0, 3), new XYZ(36, 0.5, 8), 0xA0A0A0, randomizedPoints);
AddCell(new XYZ(0, 24, 3), new XYZ(0.5, 27, 8), 0xA0A0A0, randomizedPoints);
AddCell(new XYZ(0, 27, 3), new XYZ(0.5, 30, 8), 0xA0A0A0, randomizedPoints);
AddCell(new XYZ(0, 46, 0), new XYZ(0.5, 50, 7), 0xCC99CC, randomizedPoints);
AddCell(new XYZ(0, 50, 0), new XYZ(0.5, 54, 7), 0xCC99CC, randomizedPoints);
AddCell(new XYZ(0, 70, 3), new XYZ(0.5, 73, 8), 0xA0A0A0, randomizedPoints);
AddCell(new XYZ(0, 73, 3), new XYZ(0.5, 76, 8), 0xA0A0A0, randomizedPoints);
}
#endregion
#region IPointCloudAccess Members
/// <summary>
/// The implementation of IPointCloudAccess.GetName().
/// </summary>
/// <returns>The name (the file name).</returns>
public String GetName()
{
return "apipc: " + m_identifier;
}
/// <summary>
/// The implementation of IPointCloudAccess.GetColorEncoding()
/// </summary>
/// <returns>The color encoding.</returns>
public PointCloudColorEncoding GetColorEncoding()
{
return PointCloudColorEncoding.ABGR;
}
/// <summary>
/// The implementation of IPointCloudAccess.CreatePointSetIterator().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="viewId">The view id (unused).</param>
/// <returns>The new iterator.</returns>
public IPointSetIterator CreatePointSetIterator(PointCloudFilter rFilter, ElementId viewId)
{
return new PointCloudAccessBase.PointCloudAccessBaseIterator(this, rFilter);
}
/// <summary>
/// The implementation of IPointCloudAccess.CreatePointSetIterator().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="density">The density.</param>
/// <param name="viewId">The view id (unused).</param>
/// <returns>The new iterator.</returns>
public IPointSetIterator CreatePointSetIterator(PointCloudFilter rFilter, double density, ElementId viewId)
{
throw new NotImplementedException();
}
/// <summary>
/// The implementation of IPointCloudAccess.GetExtent().
/// </summary>
/// <returns>The extents of the point cloud.</returns>
public Outline GetExtent()
{
return GetOutline();
}
/// <summary>
/// The implementation of IPointCloudAccess.GetOffset().
/// </summary>
/// <remarks>This method is not used by Revit and will be removed in a later pre-release build.</remarks>
/// <returns>Zero.</returns>
public XYZ GetOffset()
{
return XYZ.Zero;
}
/// <summary>
/// The implementation of IPointCloudAccess.GetUnitsToFeetConversionFactor().
/// </summary>
/// <returns>The scale.</returns>
public double GetUnitsToFeetConversionFactor()
{
return GetScale();
}
/// <summary>
/// The implementation of IPointCloudAccess.ReadPoints().
/// </summary>
/// <param name="rFilter">The filter.</param>
/// <param name="viewId">The view id (unused).</param>
/// <param name="buffer">The point cloud buffer.</param>
/// <param name="nBufferSize">The maximum number of points.</param>
/// <returns>The number of points read.</returns>
public int ReadPoints(PointCloudFilter rFilter, ElementId viewId, IntPtr buffer, int nBufferSize)
{
int read = ReadSomePoints(rFilter, buffer, nBufferSize, 0);
return read;
}
/// <summary>
/// The implementation of IPointCloudAccess.Free().
/// </summary>
public void Free()
{
throw new NotImplementedException();
}
#endregion
}
}
PredefinedPointCloudEngine.cs
//
// (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 Autodesk.Revit.DB;
using Autodesk.Revit.DB.PointClouds;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// The type of engine.
/// </summary>
/// <remarks>Because the same engine implementation is used for all types of engines in this sample, a member of this enumerated type
/// is used to determine the logic necessary to create the IPointCloudAccess instance.</remarks>
public enum PointCloudEngineType
{
/// <summary>
/// A predefined point cloud engine (non-randomized).
/// </summary>
Predefined,
/// <summary>
/// A predefined point cloud engine (randomized).
/// </summary>
RandomizedPoints,
/// <summary>
/// A file based point cloud engine.
/// </summary>
FileBased
}
/// <summary>
/// An implementation of IPointCloudEngine used by all the custom engines in this sample.
/// </summary>
public class BasicPointCloudEngine : IPointCloudEngine
{
#region Class Member Variables
private PointCloudEngineType m_type;
#endregion
#region Class Methods
/// <summary>
/// Constructs a new instance of the engine.
/// </summary>
/// <param name="type">The type of point cloud served by this engine instance.</param>
public BasicPointCloudEngine(PointCloudEngineType type)
{
m_type = type;
}
#endregion
#region IPointCloudEngine Members
/// <summary>
/// Implementation of IPointCloudEngine.CreatePointCloudAccess().
/// </summary>
/// <param name="identifier">The identifier (or file name) for the desired point cloud.</param>
/// <returns>The IPointCloudAccess implementation serving this point cloud.</returns>
public IPointCloudAccess CreatePointCloudAccess(string identifier)
{
switch (m_type)
{
case PointCloudEngineType.RandomizedPoints:
return new PredefinedPointCloud(identifier, true);
case PointCloudEngineType.FileBased:
return new FileBasedPointCloud(identifier);
case PointCloudEngineType.Predefined:
default:
return new PredefinedPointCloud(identifier);
}
}
/// <summary>
/// Implementation of IPointCloudEngine.Free().
/// </summary>
public void Free()
{
//Nothing to do
}
#endregion
}
}
XmlUtils.cs
//
// (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.Xml.Linq;
using System.Text;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.CS.PointCloudEngine
{
/// <summary>
/// Utilities used by the sample to process XML entries in file-based point clouds.
/// </summary>
public static class XmlUtils
{
/// <summary>
/// Gets an XYZ point from an XML element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The XYZ.</returns>
public static XYZ GetXYZ(XElement element)
{
XAttribute x = element.Attribute("X");
XAttribute y = element.Attribute("Y");
XAttribute z = element.Attribute("Z");
return new XYZ(Double.Parse(x.Value), Double.Parse(y.Value), Double.Parse(z.Value));
}
/// <summary>
/// Gets a boolean value from an XML element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The value.</returns>
public static bool GetBoolean(XElement element)
{
return Boolean.Parse(element.Attribute("value").Value);
}
/// <summary>
/// Gets a double value from an XML element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The value.</returns>
public static double GetDouble(XElement element)
{
return Double.Parse(element.Attribute("value").Value);
}
/// <summary>
/// Gets an integer value from an XML element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The value.</returns>
public static int GetInteger(XElement element)
{
return Int32.Parse(element.Attribute("value").Value);
}
/// <summary>
/// Gets a color value (in the form needed for inclusion in a CloudPoint) from an XML element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The value.</returns>
public static int GetColor(XElement element)
{
return System.Drawing.ColorTranslator.ToWin32(System.Drawing.ColorTranslator.FromHtml(element.Attribute("value").Value));
}
/// <summary>
/// Gets the XML element representing a point.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="name">The name of the XML element.</param>
/// <returns>The element.</returns>
public static XElement GetXElement(XYZ point, String name)
{
XElement ret = new XElement(name);
ret.Add(new XAttribute("X", point.X));
ret.Add(new XAttribute("Y", point.Y));
ret.Add(new XAttribute("Z", point.Z));
return ret;
}
/// <summary>
/// Gets the XML element representing a CloudPoint color.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="name">The name.</param>
/// <returns>The element.</returns>
public static XElement GetColorXElement(int color, String name)
{
XElement ret = new XElement(name);
string htmlRep = System.Drawing.ColorTranslator.ToHtml(System.Drawing.ColorTranslator.FromWin32(color));
ret.Add(new XAttribute("value", htmlRep));
return ret;
}
/// <summary>
/// Gets the XML element representing an object.
/// </summary>
/// <param name="obj">The object.</param>
/// <param name="name">The name.</param>
/// <returns>The element.</returns>
public static XElement GetXElement(object obj, String name)
{
XElement ret = new XElement(name);
ret.Add(new XAttribute("value", obj.ToString()));
return ret;
}
}
}
版权所有 :无锡模信建筑科技有限公司 苏ICP备2021028830号-1 BIM建模|BIM技术应用|BIM软件开发
联系地址:江苏省无锡市新吴区龙山路4号B座705 手机:18761516598