Title:Revit2016二次开发
Author:Kagula
Date:2015-12-01
环境
[1]Revit2016
[2]从官网下载REVIT_2016_SDK_R2.msi,用于查询Revit SDK API的用法。
参考资料[1]和自己写的Lab1PlaceGroup项目(和官网同名但是实现功能完全不同)。
部署
调试
Step1:设置项目属性
[Debug]->[Start external program]->[D:\Autodesk\Revit 2016\Revit.exe]
Step2:勾选[Visual Studio]->[Options]->[Debugging]->[Use Managed Compatibility Mode]选项。
启动项目就可以调试了。
我的Lab1PlaceGroup项目
参考资料
[1]My First Plug-in Training
http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=16777469
[2]Add-in Migration to Revit 2016 and Updated Wizards
http://thebuildingcoder.typepad.com/blog/2015/04/add-in-migration-to-revit-2016-and-updated-wizards.html
[3]My First Revit Plugin..Revit.exe' has exited with code -529697949
https://forums.autodesk.com/t5/revit-api/devtv-my-first-revit-plugin-revit-exe-has-exited-with-code/td-p/5365593
[4]Curves
http://thebuildingcoder.typepad.com/blog/2010/01/curves.html
[5]Geometry Creation and Line Intersection Exceptions
http://thebuildingcoder.typepad.com/blog/2015/05/geometry-creation-and-line-intersection-exceptions.html
[6]PART 1: CREATING A PROJECT AND ADDING LEVELS
https://knowledge.autodesk.com/support/revit-lt/getting-started/caas/CloudHelp/cloudhelp/2015/ENU/RevitLT-GetStarted/files/GUID-0E2A8A8C-2F02-46A4-9761-A47601F0B17A-htm.html
Author:Kagula
Date:2015-12-01
环境
[1]Revit2016
[2]从官网下载REVIT_2016_SDK_R2.msi,用于查询Revit SDK API的用法。
[3]Visual Studio 2013 Update5
参考资料[1]和自己写的Lab1PlaceGroup项目(和官网同名但是实现功能完全不同)。
部署
参考自己写的Lab1PlaceGroup项目中的readme文件。
前言:
花了一个工作日做了这个东西,结果没有拍上用场,只能放在这里纪念下了。
调试
Step1:设置项目属性
[Debug]->[Start external program]->[D:\Autodesk\Revit 2016\Revit.exe]
Step2:勾选[Visual Studio]->[Options]->[Debugging]->[Use Managed Compatibility Mode]选项。
启动项目就可以调试了。
我的Lab1PlaceGroup项目
MyClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Lab1PlaceGroup;
using Autodesk.Revit.DB.Structure;
using System.Text;
using Lab1PlaceGroup.Demo;
/*
* addin 文件的位置
* C:\ProgramData\Autodesk\Revit\Addins\2016
*
* "D:\Autodesk\Revit 2016\Revit.exe" /language ENU
* */
[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]
public class MyClass : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
try
{
Transaction trans = new Transaction(doc);
trans.Start("Lab");
//TestAnnotationEle.testAnnotaionEleDraw(doc);
TestAnnotationEle.testAnnotaionEleDrawFromExcel2007(doc);
trans.Commit();
return Result.Succeeded;
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return Result.Cancelled;
}
catch(Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
Level GetALevel(Document doc)
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
ICollection<Element> collection = collector.OfClass(typeof(Level)).ToElements();
foreach (Element e in collection)
{
Level level = e as Level;
if (null != level)
{
return level;
}
}
return null;
}
}
TestAnnotationEle.cs
using Autodesk.Revit.DB;
using Lab1PlaceGroup.KagulaDataType;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab1PlaceGroup.Demo
{
public static class TestAnnotationEle
{
public static void testAnnotaionEleDraw(Document doc)
{
AnnotationEleHelper.DrawDetailLine(doc, new XYZ(0, 0, 0), new XYZ(20, 0, 0));
AnnotationEleHelper.DrawDetailLine(doc, new XYZ(0, 0, 0), new XYZ(0, 10, 0));
AnnotationEleHelper.DrawArc(doc, new XYZ(1, 1, 0), new XYZ(10, 1, 0), new XYZ(5, 2, 0));
List<XYZ> ctrPoints = new List<XYZ>();
ctrPoints.Add(new XYZ(10, 1, 0));
ctrPoints.Add(new XYZ(13, 15, 0));
ctrPoints.Add(new XYZ(17, 15, 0));
ctrPoints.Add(new XYZ(20, 1, 0));
AnnotationEleHelper.DrawNurbSpline(doc, ctrPoints);
}
internal static void testAnnotaionEleDrawFromExcel2007(Document doc)
{
ExcelTable excelTable = new ExcelTable();
ArrayList arrayAnnoEle;
excelTable.ReadRecords(out arrayAnnoEle);
foreach(var e in arrayAnnoEle)
{
AnnoEleInfo ele = e as AnnoEleInfo;
switch(ele.type)
{
case "DrawDetailLine":
ParseDrawDetailLine(doc,ele);
break;
case "DrawArc":
ParseDrawArc(doc, ele);
break;
case "DrawNurbSpline":
ParseDrawNurbSpline(doc, ele);
break;
}
}
Debug.WriteLine("fafdafas");
}
internal static void ParseDrawDetailLine(Document doc,AnnoEleInfo annoEleInfo)
{
if (String.IsNullOrEmpty(annoEleInfo.arg1) || String.IsNullOrEmpty(annoEleInfo.arg2))
return;
String[] arg1 = annoEleInfo.arg1.Split(',');
String[] arg2 = annoEleInfo.arg2.Split(',');
if (arg1.Length != 3 || arg2.Length != 3)
return;
AnnotationEleHelper.DrawDetailLine(doc,
new XYZ(Convert.ToDouble(arg1[0]), Convert.ToDouble(arg1[1]), Convert.ToDouble(arg1[2])),
new XYZ(Convert.ToDouble(arg2[0]), Convert.ToDouble(arg2[1]), Convert.ToDouble(arg2[2])));
}
internal static void ParseDrawArc(Document doc,AnnoEleInfo annoEleInfo)
{
if (String.IsNullOrEmpty(annoEleInfo.arg1) ||
String.IsNullOrEmpty(annoEleInfo.arg2) ||
String.IsNullOrEmpty(annoEleInfo.arg3))
return;
String[] arg1 = annoEleInfo.arg1.Split(',');
String[] arg2 = annoEleInfo.arg2.Split(',');
String[] arg3 = annoEleInfo.arg3.Split(',');
if (arg1.Length != 3 || arg2.Length != 3 || arg3.Length != 3)
return;
AnnotationEleHelper.DrawArc(doc,
new XYZ(Convert.ToDouble(arg1[0]), Convert.ToDouble(arg1[1]), Convert.ToDouble(arg1[2])),
new XYZ(Convert.ToDouble(arg2[0]), Convert.ToDouble(arg2[1]), Convert.ToDouble(arg2[2])),
new XYZ(Convert.ToDouble(arg3[0]), Convert.ToDouble(arg3[1]), Convert.ToDouble(arg3[2])));
}
internal static void ParseDrawNurbSpline(Document doc, AnnoEleInfo annoEleInfo)
{
if (String.IsNullOrEmpty(annoEleInfo.arg1))
return;
String[] arg1 = annoEleInfo.arg1.Split(' ');
if (arg1.Length <= 3)
return;
List<XYZ> ctrPoints = new List<XYZ>();
foreach(String str in arg1)
{
String[] strXYX = str.Split(',');
if (strXYX.Length != 3)
return;
ctrPoints.Add(new XYZ(Convert.ToDouble(strXYX[0]),
Convert.ToDouble(strXYX[1]), Convert.ToDouble(strXYX[2])));
}
AnnotationEleHelper.DrawNurbSpline(doc, ctrPoints);
}
}
}
AnnoEleInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab1PlaceGroup.KagulaDataType
{
public class AnnoEleInfo
{
public String type;
public String arg1;
public String arg2;
public String arg3;
}
}
AnnotationEleHelper.cs
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab1PlaceGroup
{
static class AnnotationEleHelper
{
/*
* * 《Detail Lines》
* * http://thebuildingcoder.typepad.com/blog/2009/09/detail-lines.html
* * */
public static void DrawDetailLine(Document doc, XYZ xyzStart, XYZ xyzEnd)
{
Line geomLine = Line.CreateBound(xyzStart, xyzEnd);
DetailLine line = doc.Create.NewDetailCurve(doc.ActiveView, geomLine) as DetailLine;
}
public static void DrawArc(Document doc, XYZ xyzStart, XYZ xyzEnd, XYZ xyzOnCurve)
{
Arc geomArc = Arc.Create(xyzStart, xyzEnd, xyzOnCurve);
doc.Create.NewDetailCurve(doc.ActiveView, geomArc);
}
public static void DrawNurbSpline(Document doc, List<XYZ> ctrPoints)
{
List<double> weights = new List<double>();
for (int i = 0; i < ctrPoints.Count; i++)
{
weights.Add(1);
}
NurbSpline detailNurbSpline = NurbSpline.Create(
ctrPoints, weights);
doc.Create.NewDetailCurve(doc.ActiveView, detailNurbSpline);
}
}
}
ExcelTable.cs
using Lab1PlaceGroup.KagulaDataType;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab1PlaceGroup
{
public class ExcelTable
{
String _path;
public ExcelTable()
{
//D:\Autodesk\Revit 2016\Revit2016_注释符表.xlsx
_path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
_path += "Revit2016_注释符表.xlsx";
}
public void ReadRecords(out ArrayList arrayAnnoEle)
{
DataTable dt = ReadSheet(1);
arrayAnnoEle = new ArrayList();
foreach (DataRow dr in dt.Rows)
{
AnnoEleInfo rec = new AnnoEleInfo();
rec.type = (string)dr["类型"];
rec.arg1 = (string)dr["参数1"];
rec.arg2 = (string)dr["参数2"];
rec.arg3 = (string)dr["参数3"];
if (String.IsNullOrEmpty(rec.type))
continue;
rec.type = rec.type.Trim();
rec.arg1 = String.IsNullOrEmpty(rec.arg1) == false ? rec.arg1.Trim() : "";
rec.arg2 = String.IsNullOrEmpty(rec.arg2) == false ? rec.arg2.Trim() : "";
rec.arg3 = String.IsNullOrEmpty(rec.arg3) == false ? rec.arg3.Trim() : "";
arrayAnnoEle.Add(rec);
}
}
private DataTable ReadSheet(int indexSheet)
{
/*
* VS2013Update5下不能存取Excel2007对象的问题。
* http://stackoverflow.com/questions/20397506/class-not-registered-error-when-creating-excel-workbook-in-c-sharp
* http://stackoverflow.com/questions/26250437/exceptions-from-excel-api-after-downgrading-from-2013-to-2010
* */
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Sheets sheets;
Microsoft.Office.Interop.Excel.Workbook workbook = null;
object oMissiong = System.Reflection.Missing.Value;
System.Data.DataTable dt = new System.Data.DataTable();
try
{
workbook = app.Workbooks.Open(_path, oMissiong, oMissiong, oMissiong, oMissiong,
oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);
//将数据读入到DataTable中——Start
sheets = workbook.Worksheets;
//输入1, 读取第一张表
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(indexSheet);
if (worksheet == null)
return null;
string cellContent;
int iRowCount = worksheet.UsedRange.Rows.Count;
int iColCount = worksheet.UsedRange.Columns.Count;
Microsoft.Office.Interop.Excel.Range range;
//负责列头Start
DataColumn dc;
int ColumnID = 1;
range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, 1];
while (range.Text.ToString().Trim() != "")
{
dc = new DataColumn();
dc.DataType = System.Type.GetType("System.String");
dc.ColumnName = range.Text.ToString().Trim();
dt.Columns.Add(dc);
range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, ++ColumnID];
}
//End
for (int iRow = 2; iRow <= iRowCount; iRow++)
{
DataRow dr = dt.NewRow();
for (int iCol = 1; iCol <= iColCount; iCol++)
{
range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[iRow, iCol];
cellContent = (range.Value2 == null) ? "" : range.Text.ToString();
dr[iCol - 1] = cellContent;
}
dt.Rows.Add(dr);
}
//将数据读入到DataTable中——End
return dt;
}
catch
{
return null;
}
finally
{
workbook.Close(false, oMissiong, oMissiong);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
workbook = null;
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
}
Utils.cs
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab1PlaceGroup
{
class Utils
{
/*
* The inch is a unit of length used primarily in the imperial and U.S. customary measurement systems,
* representing 1/12 of a foot and 1/36 of a yard.
* */
public static double mmToFeet(double mm)
{
double inch = mm * 0.039370;
return inch * 12;
}
public static double feetToMM(double ft)
{
return ft * 0.00018939;
}
/*
public static XYZ GetCurveNormal(Curve curve)
{
IList<XYZ> pts = curve.Tessellate();
int n = pts.Count;
Debug.Assert(1 < n,
"expected at least two points "
+ "from curve tessellation");
XYZ p = pts[0];
XYZ q = pts[n - 1];
XYZ v = q - p;
XYZ w, normal = null;
if (2 == n)
{
Debug.Assert(curve is Line,
"expected non-line element to have "
+ "more than two tessellation points");
// for non-vertical lines, use Z axis to
// span the plane, otherwise Y axis:
double dxy = Math.Abs(v.X) + Math.Abs(v.Y);
w = (dxy > Util.TolPointOnPlane)
? XYZ.BasisZ
: XYZ.BasisY;
normal = v.CrossProduct(w).Normalize();
}
else
{
int i = 0;
while (++i < n - 1)
{
w = pts[i] - p;
normal = v.CrossProduct(w);
if (!normal.IsZeroLength())
{
normal = normal.Normalize();
break;
}
}
#if DEBUG
{
XYZ normal2;
while (++i < n - 1)
{
w = pts[i] - p;
normal2 = v.CrossProduct(w);
Debug.Assert(normal2.IsZeroLength()
|| Util.IsZero(normal2.AngleTo(normal)),
"expected all points of curve to "
+ "lie in same plane");
}
}
#endif // DEBUG
}
return normal;
}
* */
}
}
MyFirstPlugin.addin
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Command">
<Assembly>
D:\CSWorkspace\Lab1PlaceGroup\Lab1PlaceGroup\bin\Debug\Lab1PlaceGroup.dll
</Assembly>
<ClientId>502fe383-2648-4e98-adf8-5e6047f9dc34</ClientId>
<FullClassName>MyClass</FullClassName>
<Text>Lab1PlaceGroup</Text>
<VendorId>ADSK</VendorId>
<VisibilityMode>AlwaysVisible</VisibilityMode>
</AddIn>
</RevitAddIns>
readme.txt
Title: Revit2016插件DrawCurve的演示。
LastUpdateDate:2015-11-30
Author:Kagula
Revision:2
功能说明:读取Excel文件中的(Annotation Element Type)曲线信息,把它绘制到Revit2016的当前视图中。
第一部分:运行环境
运行环境1:
[1]Excel2007
[2]没有安装(或则曾经安装过)2012或以上版本的Visual Studio。
运行环境2:
如果你安装了VS2012或以上版本,请参考下面的链接手动修改注册表。
http://stackoverflow.com/questions/20397506/class-not-registered-error-when-creating-excel-workbook-in-c-sharp
http://stackoverflow.com/questions/26250437/exceptions-from-excel-api-after-downgrading-from-2013-to-2010
如果你电脑上安装了wps参考下面地址中的方法,卸载掉wps。
http://bbs.csdn.net/topics/390411260
卸载掉wps还是不能读取Excel文件内容,重新安装Office2007试试。
第二部分:如何安装
Step1:
假设你的Revit2016安装路径为"D:\Autodesk\Revit 2016"
把Revit2016_注释符表.xlsx文件复制到路径下。
Step2:修改MyFirstPlugin.addin文件中插件(Lab1PlaceGroup.dll)的位置。
然后把“MyFirstPlugin.addin”文件放到C:\ProgramData\Autodesk\Revit\Addins\2016路径下。
第三部份:如何使用
Step1:根据需要修改xlsx文件中的内容:
Revit2016_注释符表.xlsx文件演示了三种Annotation Element类型曲线的绘制。
DrawDetailLine(起点位置,终点位置);
DrawArc(起点位置,终点位置,控制点位置);
DrawNurbSpline(控制点位置1 控制点位置2 控制点位置3........控制点位置N);
控制点位置不少于四个,每个3D坐标之间以空格隔开。
Step2:
启动Revit2016,找到[Add-Ins]->[External Tools]->[Lab1PlaceGroup]按钮,点击它,就可以
导入"D:\Autodesk\Revit 2016\Revit2016_注释符表.xlsx"中描述的Annotation Element。
注意事项
[1]
“Lab1PlaceGroup”是原官方示例项目的名称,我已经完全重写了里面的代码,实现的功能同管网上的“Lab1PlaceGroup”是完全不一样的。
使用前,如果你已经安装了管网的“Lab1PlaceGroup” Example,安装本示例前,为了防止名称混淆,请先删除原来的同名控件。
[2]本项目采用VS2013Update5、Excel2007开发,但是,使用前建议目标机器没有安装过VS2012或以上版本的开发工具,免得读取Excel文件失败。
Revit2016_注释符表.xlsx
类型 | 参数1 | 参数2 | 参数3 |
DrawDetailLine | 0,0,0 | 20,0,0 | |
DrawDetailLine | 0,0,0 | 0,10,0 | |
DrawArc | 1,1,0 | 10,1,0 | 5,2,0 |
DrawNurbSpline | 10,1,0 13,15,0 17,15,0 20,1,0 |
参考资料
[1]My First Plug-in Training
http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=16777469
[2]Add-in Migration to Revit 2016 and Updated Wizards
http://thebuildingcoder.typepad.com/blog/2015/04/add-in-migration-to-revit-2016-and-updated-wizards.html
[3]My First Revit Plugin..Revit.exe' has exited with code -529697949
https://forums.autodesk.com/t5/revit-api/devtv-my-first-revit-plugin-revit-exe-has-exited-with-code/td-p/5365593
[4]Curves
http://thebuildingcoder.typepad.com/blog/2010/01/curves.html
[5]Geometry Creation and Line Intersection Exceptions
http://thebuildingcoder.typepad.com/blog/2015/05/geometry-creation-and-line-intersection-exceptions.html
[6]PART 1: CREATING A PROJECT AND ADDING LEVELS
https://knowledge.autodesk.com/support/revit-lt/getting-started/caas/CloudHelp/cloudhelp/2015/ENU/RevitLT-GetStarted/files/GUID-0E2A8A8C-2F02-46A4-9761-A47601F0B17A-htm.html
readme.txt