Revit2016二次开发

Title:Revit2016二次开发
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
DrawDetailLine0,0,020,0,0
DrawDetailLine0,0,00,10,0
DrawArc1,1,010,1,05,2,0
DrawNurbSpline10,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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kagula086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值