应用程序:NewOpenings
Revit 平台:所有
Revit 版本:2011.0
首次发布:2008.0
编程语言:C#
技能水平:高
类别:元素
类型:ExternalCommand
主题:创建开口。
摘要:
本文介绍了如何通过Revit API创建开窗。
类:
Autodesk.Revit.Creation.Application
Autodesk.Revit.Creation.Document
Autodesk.Revit.DB.Wall
Autodesk.Revit.DB.Floor
Autodesk.Revit.DB.Opening
Autodesk.Revit.DB.XYZ
Autodesk.Revit.DB.Edge
项目文件:
Command.cs
该文件包含了一个实现了IExternalCommand接口的Command类,其功能是显示主要的表单。
NewOpeningsForm.cs
该文件包含了一个NewOpeningsForm类。其功能是显示所选墙或地板的外形,并在其上绘制几何图形。
Profile.cs
该文件包含了一个抽象类Profile,该类由ProfileWall和ProfileFloor派生而来。包括两个方法Draw2D和DrawOpening,Draw2D用于在表单上绘制外形,DrawOpening用于在所选的墙或地板上创建开口。
ITool.cs
该文件包含了一个抽象类ITool,该类由ArcTool、NullTool、RectTool、CircleTool和LineTool派生而来。它们用于在NewOpeningsForm上绘制各种几何图形。
MathTools.cs
该文件包含了Verctor4和Matrix4两个类。这两个类用于将点从3D转换为2D。
描述:
本示例使用Document.NewOpening方法在选定的墙壁或地板上创建开口。可以使用Application的NewCurveArray、NewArc和NewLine方法创建外形。
操作说明:
1. 选择一个墙壁或地板。
2. 运行命令。
3. 在预览面板上绘制开口外形。单击鼠标中键可切换绘制线、矩形、弧形和圆形的工具。
4. 单击“确定”按钮,开口将被创建在墙壁或地板上。
源代码
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码
NewOpeningsForm.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.
//
namespace Revit.SDK.Samples.NewOpenings.CS
{
partial class NewOpeningsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed;
/// otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.OkButton = new System.Windows.Forms.Button();
this.openingPictureBox = new System.Windows.Forms.PictureBox();
this.cancelButton = new System.Windows.Forms.Button();
this.Notelabel = new System.Windows.Forms.Label();
this.Notelabel2 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.openingPictureBox)).BeginInit();
this.SuspendLayout();
//
// OkButton
//
this.OkButton.Location = new System.Drawing.Point(221, 439);
this.OkButton.Name = "OkButton";
this.OkButton.Size = new System.Drawing.Size(80, 26);
this.OkButton.TabIndex = 0;
this.OkButton.Text = "&OK";
this.OkButton.UseVisualStyleBackColor = true;
this.OkButton.Click += new System.EventHandler(this.OkButton_Click);
//
// openingPictureBox
//
this.openingPictureBox.BackColor = System.Drawing.SystemColors.Window;
this.openingPictureBox.Dock = System.Windows.Forms.DockStyle.Top;
this.openingPictureBox.Location = new System.Drawing.Point(0, 0);
this.openingPictureBox.Name = "openingPictureBox";
this.openingPictureBox.Size = new System.Drawing.Size(415, 381);
this.openingPictureBox.TabIndex = 1;
this.openingPictureBox.TabStop = false;
this.openingPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.openingPictureBox_MouseDown);
this.openingPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.openingPictureBox_MouseMove);
this.openingPictureBox.Paint += new System.Windows.Forms.PaintEventHandler(this.openingPictureBox_Paint);
this.openingPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.openingPictureBox_MouseUp);
//
// cancelButton
//
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(316, 439);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(80, 26);
this.cancelButton.TabIndex = 1;
this.cancelButton.Text = "&Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// Notelabel
//
this.Notelabel.AutoSize = true;
this.Notelabel.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Notelabel.Location = new System.Drawing.Point(-3, 393);
this.Notelabel.Name = "Notelabel";
this.Notelabel.Size = new System.Drawing.Size(415, 13);
this.Notelabel.TabIndex = 2;
this.Notelabel.Text = " Use middle button of mouse to switch tool to draw Opening in Preview";
//
// Notelabel2
//
this.Notelabel2.AutoSize = true;
this.Notelabel2.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Notelabel2.Location = new System.Drawing.Point(-3, 416);
this.Notelabel2.Name = "Notelabel2";
this.Notelabel2.Size = new System.Drawing.Size(270, 13);
this.Notelabel2.TabIndex = 3;
this.Notelabel2.Text = " Click right button of mouse to close the lines";
//
// NewOpeningsForm
//
this.AcceptButton = this.OkButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(415, 473);
this.Controls.Add(this.Notelabel2);
this.Controls.Add(this.Notelabel);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.openingPictureBox);
this.Controls.Add(this.OkButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "NewOpeningsForm";
this.ShowInTaskbar = false;
this.Text = "New Openings";
((System.ComponentModel.ISupportInitialize)(this.openingPictureBox)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button OkButton;
private System.Windows.Forms.PictureBox openingPictureBox;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Label Notelabel;
private System.Windows.Forms.Label Notelabel2;
}
}
Profile.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.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit;
using System.Drawing;
using Point = System.Drawing.Point;
namespace Revit.SDK.Samples.NewOpenings.CS
{
/// <summary>
/// Base class of ProfileFloor and ProfileWall
/// contain the profile information and can make matrix to transform point to 2D plane
/// </summary>
public abstract class Profile
{
#region members
/// <summary>
///Wall or Floor element
/// </summary>
protected Autodesk.Revit.DB.Element m_dataProfile;
/// <summary>
/// geometry object [face]
/// </summary>
protected List<Edge> m_face;
/// <summary>
/// command data
/// </summary>
protected Autodesk.Revit.UI.ExternalCommandData m_commandData;
/// <summary>
/// Application creator
/// </summary>
protected Autodesk.Revit.Creation.Application m_appCreator;
/// <summary>
/// Document creator
/// </summary>
protected Autodesk.Revit.Creation.Document m_docCreator;
#endregion
/// <summary>
/// Abstract method to create Opening
/// </summary>
public abstract void DrawOpening(List<Vector4> points, ToolType type);
/// <summary>
/// Draw profile of wall or floor in 2D
/// </summary>
/// <param name="graphics">form graphic</param>
/// <param name="pen">pen use to draw line in pictureBox</param>
/// <param name="matrix4">matrix used to transform points between 3d and 2d.</param>>
public void Draw2D(Graphics graphics, Pen pen, Matrix4 matrix4)
{
foreach (Edge edge in m_face)
{
List<XYZ> points = edge.Tessellate() as List<XYZ>;
for (int i = 0; i < points.Count - 1; i++)
{
Autodesk.Revit.DB.XYZ point1 = points[i];
Autodesk.Revit.DB.XYZ point2 = points[i + 1];
Vector4 v1 = new Vector4(point1);
Vector4 v2 = new Vector4(point2);
v1 = matrix4.TransForm(v1);
v2 = matrix4.TransForm(v2);
graphics.DrawLine(pen, new Point((int)v1.X, (int)v1.Y),
new Point((int)v2.X, (int)v2.Y));
}
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="elem">Selected element</param>
/// <param name="commandData">ExternalCommandData</param>
public Profile(Autodesk.Revit.DB.Element elem, ExternalCommandData commandData)
{
m_dataProfile = elem;
m_commandData = commandData;
m_appCreator = m_commandData.Application.Application.Create;
m_docCreator = m_commandData.Application.ActiveUIDocument.Document.Create;
List<List<Edge>> faces = GetFaces(m_dataProfile);
m_face = GetNeedFace(faces);
}
/// <summary>
/// Get edges of element's profile
/// </summary>
/// <param name="elem">Selected element</param>
public List<List<Edge>> GetFaces(Autodesk.Revit.DB.Element elem)
{
List<List<Edge>> faceEdges = new List<List<Edge>>();
Options options = m_appCreator.NewGeometryOptions();
options.DetailLevel = ViewDetailLevel.Medium;
options.ComputeReferences = true;
Autodesk.Revit.DB.GeometryElement geoElem = elem.get_Geometry(options);
//GeometryObjectArray gObjects = geoElem.Objects;
IEnumerator<GeometryObject> Objects = geoElem.GetEnumerator();
//foreach (GeometryObject geo in gObjects)
while (Objects.MoveNext())
{
GeometryObject geo = Objects.Current;
Solid solid = geo as Solid;
if (solid != null)
{
EdgeArray edges = solid.Edges;
FaceArray faces = solid.Faces;
foreach (Face face in faces)
{
EdgeArrayArray edgeArrarr = face.EdgeLoops;
foreach (EdgeArray edgeArr in edgeArrarr)
{
List<Edge> edgesList = new List<Edge>();
foreach (Edge edge in edgeArr)
{
edgesList.Add(edge);
}
faceEdges.Add(edgesList);
}
}
}
}
return faceEdges;
}
/// <summary>
/// Get Face Normal
/// </summary>
/// <param name="face">Edges in a face</param>
private Vector4 GetFaceNormal(List<Edge> face)
{
Edge eg0 = face[0];
Edge eg1 = face[1];
List<XYZ> points = eg0.Tessellate() as List<XYZ>;
Autodesk.Revit.DB.XYZ start = points[0];
Autodesk.Revit.DB.XYZ end = points[1];
Vector4 vStart = new Vector4((float)start.X, (float)start.Y, (float)start.Z);
Vector4 vEnd = new Vector4((float)end.X, (float)end.Y, (float)end.Z);
Vector4 vSub = vEnd - vStart;
points = eg1.Tessellate() as List<XYZ>;
start = points[0];
end = points[1];
vStart = new Vector4((float)start.X, (float)start.Y, (float)start.Z);
vEnd = new Vector4((float)end.X, (float)end.Y, (float)end.Z);
Vector4 vSub2 = vEnd - vStart;
Vector4 result = vSub.CrossProduct(vSub2);
result.Normalize();
return result;
}
/// <summary>
/// Get First Face
/// </summary>
/// <param name="faces">edges in all faces</param>
private List<Edge> GetNeedFace(List<List<Edge>> faces)
{
if (m_dataProfile is Wall)
{
return GetWallFace(faces);
}
return faces[0];
}
/// <summary>
/// Get a matrix which can transform points to 2D
/// </summary>
public Matrix4 To2DMatrix()
{
if (m_dataProfile is Wall)
{
return WallMatrix();
}
List<XYZ> eg0 = m_face[0].Tessellate() as List<XYZ>;
List<XYZ> eg1 = m_face[1].Tessellate() as List<XYZ>;
Vector4 v1 = new Vector4((float)eg0[0].X,
(float)eg0[0].Y, (float)eg0[0].Z);
Vector4 v2 = new Vector4((float)eg0[1].X,
(float)eg0[1].Y, (float)eg0[1].Z);
Vector4 v21 = v1 - v2;
v21.Normalize();
Vector4 v3 = new Vector4((float)eg1[0].X,
(float)eg1[0].Y, (float)eg1[0].Z);
Vector4 v4 = new Vector4((float)eg1[1].X,
(float)eg1[1].Y, (float)eg1[1].Z);
Vector4 v43 = v4 - v3;
v43.Normalize();
Vector4 vZAxis = Vector4.CrossProduct(v43, v21);
Vector4 vYAxis = Vector4.CrossProduct(vZAxis, v43);
vYAxis.Normalize();
vZAxis.Normalize();
Vector4 vOrigin = (v4 + v1) / 2;
Matrix4 result = new Matrix4(v43, vYAxis, vZAxis, vOrigin);
return result;
}
/// <summary>
/// Wall matrix
/// </summary>
/// <returns></returns>
public Matrix4 WallMatrix()
{
//get the location curve
LocationCurve location = m_dataProfile.Location as LocationCurve;
Vector4 xAxis = new Vector4(1, 0, 0);
Vector4 yAxis = new Vector4(0, 1, 0);
Vector4 zAxis = new Vector4(0, 0, 1);
Vector4 origin = new Vector4(0, 0, 0);
if (location != null)
{
Curve curve = location.Curve;
Autodesk.Revit.DB.XYZ start = curve.GetEndPoint(0);
Autodesk.Revit.DB.XYZ end = curve.GetEndPoint(1);
xAxis = new Vector4((float)(end.X - start.X),
(float)(end.Y - start.Y), (float)(end.Z - start.Z));
xAxis.Normalize();
yAxis = new Vector4(0, 0, 1);
zAxis = Vector4.CrossProduct(xAxis, yAxis);
zAxis.Normalize();
origin = new Vector4((float)(end.X + start.X) / 2,
(float)(end.Y + start.Y) / 2, (float)(end.Z + start.Z) / 2);
}
return new Matrix4(xAxis, yAxis, zAxis, origin);
}
/// <summary>
/// Get wall face
/// </summary>
/// <param name="faces"></param>
/// <returns></returns>
private List<Edge> GetWallFace(List<List<Edge>> faces)
{
LocationCurve location = m_dataProfile.Location as LocationCurve;
Curve curve = location.Curve;
List<XYZ> xyzs = curve.Tessellate() as List<XYZ>;
Vector4 zAxis = new Vector4(0, 0, 1);
if (xyzs.Count == 2)
{
return faces[0];
}
foreach (List<Edge> face in faces)
{
foreach (Edge edge in face)
{
List<XYZ> edgexyzs = edge.Tessellate() as List<XYZ>;
if (xyzs.Count == edgexyzs.Count)
{
Vector4 normal = GetFaceNormal(face);
Vector4 cross = Vector4.CrossProduct(zAxis, normal);
cross.Normalize();
if (cross.Length() == 1)
{
return face;
}
}
}
}
return faces[0];
}
/// <summary>
/// Get a matrix which can move points to origin
/// </summary>
public Matrix4 ToCenterMatrix()
{
//translate the origin to bound center
PointF[] bounds = GetFaceBounds();
PointF min = bounds[0];
PointF max = bounds[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));
}
/// <summary>
/// Get Face Bounds
/// </summary>
public PointF[] GetFaceBounds()
{
Matrix4 matrix = To2DMatrix();
Matrix4 inverseMatrix = matrix.Inverse();
float minX = 0, maxX = 0, minY = 0, maxY = 0;
bool bFirstPoint = true;
foreach (Edge edge in m_face)
{
List<XYZ> points = edge.Tessellate() as List<XYZ>;
foreach (Autodesk.Revit.DB.XYZ point in points)
{
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;
}
}
}
}
PointF[] resultPoints = new PointF[2] {
new PointF(minX, minY), new PointF(maxX, maxY) };
return resultPoints;
}
}
}
ITool.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.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing;
namespace Revit.SDK.Samples.NewOpenings.CS
{
/// <summary>
/// Stand for the draw tool type
/// </summary>
public enum ToolType
{
/// <summary>
/// Draw nothing
/// </summary>
None,
/// <summary>
/// Draw polygon
/// </summary>
Line,
/// <summary>
/// Draw rectangle
/// </summary>
Rectangle,
/// <summary>
/// Draw circle
/// </summary>
Circle,
/// <summary>
/// Draw arc
/// </summary>
Arc
}
/// <summary>
/// Abstract class use as base class of all draw tool class
/// </summary>
public abstract class ITool
{
# region members
/// <summary>
/// ToolType is enum type indicate draw tools.
/// </summary>
protected ToolType m_type;
/// <summary>
/// Field used to store points of a line
/// </summary>
protected List<Point> m_points = new List<Point>();
/// <summary>
/// Field used to store lines
/// </summary>
protected List<List<Point>> m_lines = new List<List<Point>>();
/// <summary>
/// Background pen used to erase the preview line
/// </summary>
protected Pen m_backGroundPen;
/// <summary>
/// Foreground pen used to draw lines
/// </summary>
protected Pen m_foreGroundPen;
/// <summary>
/// Store the mouse position when mouse move in pictureBox
/// </summary>
protected Point m_preMovePoint;
#endregion
/// <summary>
/// Default constructor
/// </summary>
public ITool()
{
m_backGroundPen = Pens.White;
m_foreGroundPen = Pens.Red;
}
/// <summary>
/// Get all lines drawn in pictureBox
/// </summary>
public List<List<Point>> GetLines()
{
return m_lines;
}
/// <summary>
/// Get the tool type
/// </summary>
public virtual ToolType ToolType
{
get
{
return m_type;
}
}
/// <summary>
/// Right mouse click event handler
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
/// <param name="e">Mouse event argument</param>
public virtual void OnRightMouseClick(Graphics graphic, MouseEventArgs e) { }
/// <summary>
/// Mouse move event handler
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
/// <param name="e">Mouse event argument</param>
public virtual void OnMouseMove(Graphics graphic, MouseEventArgs e) { }
/// <summary>
/// Mouse down event handler
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
/// <param name="e">Mouse event argument</param>
public virtual void OnMouseDown(Graphics graphic, MouseEventArgs e) { }
/// <summary>
/// Mouse up event handler
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
/// <param name="e">Mouse event argument</param>
public virtual void OnMouseUp(Graphics graphic, MouseEventArgs e) { }
/// <summary>
/// Mouse middle key down event handler
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
/// <param name="e">Mouse event argument</param>
public virtual void OnMidMouseDown(Graphics graphic, MouseEventArgs e)
{
this.m_points.Clear();
}
/// <summary>
/// Draw geometries contained in the tool. which class derived from this class
/// must implement this abstract method
/// </summary>
/// <param name="graphic">Graphics object, used to draw geometry</param>
public abstract void Draw(Graphics graphic);
}
}
MathTools.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.Text;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.NewOpenings.CS
{
/// <summary>
/// Vector4 class use to store vector
/// and contain method to handle the vector
/// </summary>
public class Vector4
{
#region Member and propertys
/// <summary>
/// The coordinate x value
/// </summary>
private float m_x;
/// <summary>
/// The coordinate y value
/// </summary>
private float m_y;
/// <summary>
/// The coordinate z value
/// </summary>
private float m_z;
/// <summary>
/// The coordinate w value
/// </summary>
private float m_w = 1.0f;
/// <summary>
/// The coordinate x value
/// </summary>
public float X
{
get
{
return m_x;
}
set
{
m_x = value;
}
}
/// <summary>
///The coordinate y value
/// </summary>
public float Y
{
get
{
return m_y;
}
set
{
m_y = value;
}
}
/// <summary>
/// The coordinate z value
/// </summary>
public float Z
{
get
{
return m_z;
}
set
{
m_z = value;
}
}
/// <summary>
/// The coordinate w value
/// </summary>
public float W
{
get
{
return m_w;
}
set
{
m_w = value;
}
}
#endregion
/// <summary>
/// Constructor
/// </summary>
public Vector4(float x, float y, float z)
{
this.X = x; this.Y = y; this.Z = z;
}
/// <summary>
/// Copy constructor
/// </summary>
public Vector4( Vector4 v)
{
this.X = v.X; this.Y = v.Y; this.Z = v.Z;
}
/// <summary>
/// Constructor, transform Autodesk.Revit.DB.XYZ to vector
/// </summary>
public Vector4(Autodesk.Revit.DB.XYZ v)
{
this.X = (float)v.X; this.Y = (float)v.Y; this.Z = (float)v.Z;
}
/// <summary>
/// Add two vector
/// </summary>
/// <param name="va">First vector</param>
/// <param name="vb">Second vector</param>
public static Vector4 operator+ (Vector4 va, Vector4 vb)
{
return new Vector4(va.X + vb.X, va.Y + vb.Y, va.Z + vb.Z);
}
/// <summary>
/// Subtraction of two vector
/// </summary>
/// <param name="va">First vector</param>
/// <param name="vb">Second vector</param>
/// <returns>Subtraction of two vector</returns>
public static Vector4 operator- (Vector4 va, Vector4 vb)
{
return new Vector4(va.X - vb.X, va.Y - vb.Y, va.Z - vb.Z);
}
/// <summary>
/// Get vector multiply by an double value
/// </summary>
/// <param name="v">Vector</param>
/// <param name="factor">Double value</param>
/// <returns> Vector multiply by an double value</returns>
public static Vector4 operator* (Vector4 v,float factor)
{
return new Vector4(v.X * factor, v.Y * factor, v.Z * factor);
}
/// <summary>
/// get vector divided by an double value
/// </summary>
/// <param name="v">vector</param>
/// <param name="factor">double value</param>
/// <returns> vector divided by an double value</returns>
public static Vector4 operator /(Vector4 v, float factor)
{
return new Vector4(v.X / factor, v.Y / factor, v.Z / factor);
}
/// <summary>
/// dot multiply vector
/// </summary>
/// <param name="v">vector</param>
public float DotProduct(Vector4 v)
{
return (this.X * v.X + this.Y * v.Y + this.Z * v.Z);
}
/// <summary>
/// get normal vector of two vector
/// </summary>
/// <param name="v">second vector</param>
/// <returns> normal vector of two vector</returns>
public Vector4 CrossProduct(Vector4 v)
{
return new Vector4(this.Y * v.Z - this.Z * v.Y,this.Z * v.X
- this.X * v.Z,this.X * v.Y - this.Y * v.X);
}
/// <summary>
/// Dot multiply two vector
/// </summary>
/// <param name="va">First vector</param>
/// <param name="vb">Second vector</param>
public static float DotProduct(Vector4 va, Vector4 vb)
{
return (va.X * vb.X + va.Y * vb.Y + va.Z * vb.Z);
}
/// <summary>
/// Get normal vector of two vector
/// </summary>
/// <param name="va">First vector</param>
/// <param name="vb">Second vector</param>
/// <returns> Normal vector of two vector</returns>
public static Vector4 CrossProduct(Vector4 va, Vector4 vb)
{
return new Vector4(va.Y * vb.Z - va.Z * vb.Y, va.Z * vb.X
- va.X * vb.Z, va.X * vb.Y - va.Y * vb.X);
}
/// <summary>
/// Get unit vector
/// </summary>
public void Normalize()
{
float length = Length();
if(length == 0)
{
length = 1;
}
this.X /= length;
this.Y /= length;
this.Z /= length;
}
/// <summary>
/// Calculate the length of vector
/// </summary>
public float Length()
{
return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
}
};
/// <summary>
/// Matrix used to transform between UCS coordinate and world coordinate.
/// </summary>
public class Matrix4
{
#region MatrixType
/// <summary>
/// matrix algorithm
/// </summary>
public enum MatrixType
{
/// <summary>
/// rotation matrix
/// </summary>
Rotation,
/// <summary>
/// translation matrix
/// </summary>
TransLation,
/// <summary>
/// scale matrix
/// </summary>
Scale,
/// <summary>
/// rotation and translation mix matrix
/// </summary>
RotationAndTransLation,
/// <summary>
/// identity matrix
/// </summary>
Normal
};
private float[,] m_matrix = new float[4,4];
private MatrixType m_type;
#endregion
/// <summary>
/// Construct a identity matrix
/// </summary>
public Matrix4()
{
m_type = MatrixType.Normal;
Identity();
}
/// <summary>
/// Construct a rotation matrix,origin at (0,0,0)
/// </summary>
/// <param name="xAxis">identity of x axis</param>
/// <param name="yAxis">identity of y axis</param>
/// <param name="zAxis">identity of z axis</param>
public Matrix4(Vector4 xAxis,Vector4 yAxis, Vector4 zAxis)
{
m_type = MatrixType.Rotation;
Identity();
m_matrix[0, 0] = xAxis.X; m_matrix[0, 1] = xAxis.Y; m_matrix[0, 2] = xAxis.Z;
m_matrix[1, 0] = yAxis.X; m_matrix[1, 1] = yAxis.Y; m_matrix[1, 2] = yAxis.Z;
m_matrix[2, 0] = zAxis.X; m_matrix[2, 1] = zAxis.Y; m_matrix[2, 2] = zAxis.Z;
}
/// <summary>
/// ctor,translation matrix.
/// </summary>
/// <param name="origin">origin of UCS in world coordinate</param>
public Matrix4(Vector4 origin)
{
m_type = MatrixType.TransLation;
Identity();
m_matrix[3, 0] = origin.X; m_matrix[3, 1] = origin.Y; m_matrix[3, 2] = origin.Z;
}
/// <summary>
/// rotation and translation matrix constructor
/// </summary>
/// <param name="xAxis">x Axis</param>
/// <param name="yAxis">y Axis</param>
/// <param name="zAxis">z Axis</param>
/// <param name="origin">origin</param>
public Matrix4(Vector4 xAxis, Vector4 yAxis, Vector4 zAxis, Vector4 origin)
{
m_type = MatrixType.RotationAndTransLation;
Identity();
m_matrix[0, 0] = xAxis.X; m_matrix[0, 1] = xAxis.Y; m_matrix[0, 2] = xAxis.Z;
m_matrix[1, 0] = yAxis.X; m_matrix[1, 1] = yAxis.Y; m_matrix[1, 2] = yAxis.Z;
m_matrix[2, 0] = zAxis.X; m_matrix[2, 1] = zAxis.Y; m_matrix[2, 2] = zAxis.Z;
m_matrix[3, 0] = origin.X; m_matrix[3, 1] = origin.Y; m_matrix[3, 2] = origin.Z;
}
/// <summary>
/// scale matrix constructor
/// </summary>
/// <param name="scale">scale factor</param>
public Matrix4(float scale)
{
m_type = MatrixType.Scale;
Identity();
m_matrix[0, 0] = m_matrix[1, 1] = m_matrix[2, 2] = scale;
}
/// <summary>
/// indexer of matrix
/// </summary>
/// <param name="row">row number</param>
/// <param name="column">column number</param>
/// <returns></returns>
public float this[int row,int column]
{
get
{
return this.m_matrix[row, column];
}
set
{
this.m_matrix[row, column] = value;
}
}
/// <summary>
/// Identity matrix
/// </summary>
public void Identity()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
this.m_matrix[i, j] = 0.0f;
}
}
this.m_matrix[0, 0] = 1.0f;
this.m_matrix[1, 1] = 1.0f;
this.m_matrix[2, 2] = 1.0f;
this.m_matrix[3, 3] = 1.0f;
}
/// <summary>
/// Multiply matrix left and right
/// </summary>
/// <param name="left">Left matrix</param>
/// <param name="right">Right matrix</param>
/// <returns></returns>
public static Matrix4 Multiply(Matrix4 left, Matrix4 right)
{
Matrix4 result = new Matrix4();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
result[i, j] = left[i, 0] * right[0, j] + left[i, 1] * right[1, j]
+ left[i, 2] * right[2, j] + left[i, 3] * right[3, j];
}
}
return result;
}
/// <summary>
/// Transform point use this matrix
/// </summary>
/// <param name="point">Point needed to be transformed</param>
/// <returns>Transform result</returns>
public Vector4 TransForm(Vector4 point)
{
return new Vector4(point.X * this[0, 0] + point.Y * this[1, 0]
+ point.Z * this[2, 0]+ point.W * this[3, 0],
point.X * this[0, 1] + point.Y * this[1, 1]
+ point.Z * this[2, 1]+ point.W * this[3, 1],
point.X * this[0, 2] + point.Y * this[1, 2]
+ point.Z * this[2, 2]+ point.W * this[3, 2]);
}
/// <summary>
/// If it is a rotation matrix,this method can get the rotation inverse matrix.
/// </summary>
/// <returns>rotation inverse matrix</returns>
public Matrix4 RotationInverse()
{
return new Matrix4(new Vector4(this[0, 0], this[1, 0], this[2, 0]),
new Vector4(this[0, 1], this[1, 1], this[2, 1]),
new Vector4(this[0, 2], this[1, 2], this[2, 2]));
}
/// <summary>
/// If it is a translation matrix,
/// this method can get the translation inverse matrix.
/// </summary>
/// <returns>translation inverse matrix</returns>
public Matrix4 TransLationInverse()
{
return new Matrix4(new Vector4(-this[3, 0], -this[3, 1], -this[3, 2]));
}
/// <summary>
/// Get inverse matrix
/// </summary>
/// <returns>Inverse matrix</returns>
public Matrix4 Inverse()
{
switch(m_type)
{
case MatrixType.Rotation:
return RotationInverse();
case MatrixType.TransLation:
return TransLationInverse();
case MatrixType.RotationAndTransLation:
return Multiply(TransLationInverse(),RotationInverse());
case MatrixType.Scale:
return ScaleInverse();
case MatrixType.Normal:
return new Matrix4();
default: return null;
}
}
/// <summary>
/// If it is a scale matrix,this method can get the scale inverse matrix.
/// </summary>
/// <returns>Scale inverse matrix</returns>
public Matrix4 ScaleInverse()
{
return new Matrix4(1 / m_matrix[0,0]);
}
};
}
版权所有 :无锡模信建筑科技有限公司 苏ICP备2021028830号-1 BIM建模|BIM技术应用|BIM软件开发
联系地址:江苏省无锡市新吴区龙山路4号B座705 手机:18761516598