应用程序名称: GenerateFloor

Revit 平台: 所有版本

Revit 版本: 2011.0

首次发布版本: 9.0

编程语言: C#

技能等级: 中等

类别: 元素

类型: 外部命令

主题: 使用选定的墙的闭合轮廓生成地板。

摘要:

这个示例演示了如何使用由选定的墙构成的封闭轮廓生成地板。

相关类:

Autodesk.Revit.Creation.Document

Autodesk.Revit.DB.Floor

Autodesk.Revit.DB.FloorType

Autodesk.Revit.DB.Level

项目文件:

Command.cs

这是主要的DLL源文件。它包含了实现接口IExternalCommand的类Command

 

Data.cs

这是示例项目的最重要的类,获取此示例的所有数据:用于地板的所有可能类型、墙所基于的楼层。

 

GenerateFloorForm.cs

一个对话框,包含以下内容:

- 一个下拉列表框,包含所有地板类型。

- 一个复选框,显示要创建的地板是结构地板还是非结构地板。

- 一个预览窗口,应该显示封闭轮廓。

描述:

- 地板的轮廓可以从墙体的位置中获取。如果这个曲线数组没有按顺序排列,使用该轮廓创建地板将会遇到异常。解决方法是首先按顺序排列这些曲线。

- RevitAPI 10 之前,“NewFloor” 方法是创建 FloorSlabFoundation Slab 等对象的唯一接口。从 RevitAPI 10 开始,它被分为三个方法:“NewFloor”,“NewSlab” 和 “NewFoundationSlab”。

说明:

1. 选择几堵构成一个封闭轮廓的墙。

2. 运行这个外部命令,一个对话框将显示您想要创建的地板轮廓。

3. 选择您想创建的地板类型。

4. 点击“确认”按钮,地板将被创建。

源代码:

完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

Data.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.Collections;
using System.Drawing;

using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace Revit.SDK.Samples.GenerateFloor.CS
{
   /// <summary>
   /// obtain all data for this sample.
   /// all possible types for floor
   /// the level that walls based
   /// </summary>
   public class Data
   {
      private Hashtable m_floorTypes;
      private List<string> m_floorTypesName;
      private FloorType m_floorType;
      private Level m_level;
      private CurveArray m_profile;
      private bool m_structural;
      private System.Drawing.PointF[] m_points;
      private double m_maxLength;
      private const double PRECISION = 0.00000001;
      private Autodesk.Revit.Creation.Application m_creApp;
      private Document m_document;

      /// <summary>
      /// A floor type to be used by the new floor instead of the default type.
      /// </summary>
      public FloorType FloorType
      {
         get
         {
            return m_floorType;
         }
         set
         {
            m_floorType = value;
         }
      }

      /// <summary>
      /// The level on which the floor is to be placed.
      /// </summary>
      public Level Level
      {
         get
         {
            return m_level;
         }
         set
         {
            m_level = value;
         }
      }

      /// <summary>
      /// A array of planar lines and arcs that represent the horizontal profile of the floor.
      /// </summary>
      public CurveArray Profile
      {
         get
         {
            return m_profile;
         }
         set
         {
            m_profile = value;
         }
      }

      /// <summary>
      /// If set, specifies that the floor is structural in nature.
      /// </summary>
      public bool Structural
      {
         get
         {
            return m_structural;
         }
         set
         {
            m_structural = value;
         }
      }

      /// <summary>
      /// Points to be draw.
      /// </summary>
      public System.Drawing.PointF[] Points
      {
         get
         {
            return m_points;
         }
         set
         {
            m_points = value;
         }
      }

      /// <summary>
      /// the graphics' max length
      /// </summary>
      public double MaxLength
      {
         get
         {
            return m_maxLength;
         }
         set
         {
            m_maxLength = value;
         }
      }

      /// <summary>
      /// List of all floor types name could be used by the floor.
      /// </summary>
      public List<string> FloorTypesName
      {
         get
         {
            return m_floorTypesName;
         }
         set
         {
            m_floorTypesName = value;
         }
      }

      /// <summary>
      /// Obtain all data which is necessary for generate floor.
      /// </summary>
      /// <param name="commandData">An object that is passed to the external application 
      /// which contains data related to the command, 
      /// such as the application object and active view.</param>
      public void ObtainData(ExternalCommandData commandData)
      {
         if (null == commandData)
         {
            throw new ArgumentNullException("commandData");
         }

         UIDocument doc = commandData.Application.ActiveUIDocument;
         m_document = doc.Document;
         ElementSet es = new ElementSet();
         foreach (ElementId elementId in doc.Selection.GetElementIds())
         {
            es.Insert(doc.Document.GetElement(elementId));
         }
         ElementSet walls = WallFilter(es);
         m_creApp = commandData.Application.Application.Create;
         Profile = m_creApp.NewCurveArray();

         FilteredElementIterator iter = (new FilteredElementCollector(doc.Document)).OfClass(typeof(FloorType)).GetElementIterator();
         ObtainFloorTypes(iter);
         ObtainProfile(walls);
         ObtainLevel(walls);
         Generate2D();
         Structural = true;
      }

      /// <summary>
      /// Set the floor type to generate by its name.
      /// </summary>
      /// <param name="typeName">the floor type's name</param>
      public void ChooseFloorType(string typeName)
      {
         FloorType = m_floorTypes[typeName] as FloorType;
      }

      /// <summary>
      /// Obtain all types are available for floor.
      /// </summary>
      /// <param name="elements">all elements within the Document.</param>
      private void ObtainFloorTypes(FilteredElementIterator elements)
      {
         m_floorTypes = new Hashtable();
         FloorTypesName = new List<string>();

         elements.Reset();
         while (elements.MoveNext())
         {
            Autodesk.Revit.DB.FloorType ft = elements.Current as Autodesk.Revit.DB.FloorType;

            if (null == ft || null == ft.Category || !ft.Category.Name.Equals("Floors"))
            {
               continue;
            }

            m_floorTypes.Add(ft.Name, ft);
            FloorTypesName.Add(ft.Name);
            FloorType = ft;
         }
      }

      /// <summary>
      /// Obtain the wall's level
      /// </summary>
      /// <param name="walls">the selection of walls that make a closed outline </param>
      private void ObtainLevel(ElementSet walls)
      {
         Autodesk.Revit.DB.Level temp = null;

         foreach (Wall w in walls)
         {
            if (null == temp)
            {
                temp = m_document.GetElement(w.LevelId) as Level;
               Level = temp;
            }

            if (Level.Elevation != (m_document.GetElement(w.LevelId) as Level).Elevation)
            {
               throw new InvalidOperationException("All walls should base the same level.");
            }
         }
      }

      /// <summary>
      /// Obtain a profile to generate floor.
      /// </summary>
      /// <param name="walls">the selection of walls that make a closed outline</param>
      private void ObtainProfile(ElementSet walls)
      {
         CurveArray temp = new CurveArray();
         foreach (Wall w in walls)
         {
            LocationCurve curve = w.Location as LocationCurve;
            temp.Append(curve.Curve);
         }
         SortCurves(temp);
      }

      /// <summary>
      /// Generate 2D data for preview pane.
      /// </summary>
      private void Generate2D()
      {
         ArrayList tempArray = new ArrayList();
         double xMin = 0;
         double xMax = 0;
         double yMin = 0;
         double yMax = 0;

         foreach (Curve c in Profile)
         {
            List<XYZ> xyzArray = c.Tessellate() as List<XYZ>;
            foreach (Autodesk.Revit.DB.XYZ xyz in xyzArray)
            {
               Autodesk.Revit.DB.XYZ temp = new Autodesk.Revit.DB.XYZ(xyz.X, -xyz.Y, xyz.Z);
               FindMinMax(temp, ref xMin, ref xMax, ref yMin, ref yMax);
               tempArray.Add(temp);
            }
         }

         MaxLength = ((xMax - xMin) > (yMax - yMin)) ? (xMax - xMin) : (yMax - yMin);

         Points = new PointF[tempArray.Count / 2 + 1];
         for (int i = 0; i < tempArray.Count; i = i + 2)
         {
            Autodesk.Revit.DB.XYZ point = (Autodesk.Revit.DB.XYZ)tempArray[i];
            Points.SetValue(new PointF((float)(point.X - xMin), (float)(point.Y - yMin)), i / 2);
         }
         PointF end = (PointF)Points.GetValue(0);
         Points.SetValue(end, tempArray.Count / 2);
      }

      /// <summary>
      /// Estimate the current point is left_bottom or right_up.
      /// </summary>
      /// <param name="point">current point</param>
      /// <param name="xMin">left</param>
      /// <param name="xMax">right</param>
      /// <param name="yMin">bottom</param>
      /// <param name="yMax">up</param>
      static private void FindMinMax(Autodesk.Revit.DB.XYZ point, ref double xMin, ref double xMax, ref double yMin, ref double yMax)
      {
         if (point.X < xMin)
         {
            xMin = point.X;
         }
         if (point.X > xMax)
         {
            xMax = point.X;
         }
         if (point.Y < yMin)
         {
            yMin = point.Y;
         }
         if (point.Y > yMax)
         {
            yMax = point.Y;
         }
      }

      /// <summary>
      /// Filter none-wall elements.
      /// </summary>
      /// <param name="miscellanea">The currently selected Elements in Autodesk Revit</param>
      /// <returns></returns>
      static private ElementSet WallFilter(ElementSet miscellanea)
      {
         ElementSet walls = new ElementSet();
         foreach (Autodesk.Revit.DB.Element e in miscellanea)
         {
            Wall w = e as Wall;
            if (null != w)
            {
               walls.Insert(w);
            }
         }

         if (0 == walls.Size)
         {
            throw new InvalidOperationException("Please select wall first.");
         }

         return walls;
      }

      /// <summary>
      /// Chaining the profile.
      /// </summary>
      /// <param name="lines">none-chained profile</param>
      private void SortCurves(CurveArray lines)
      {
         Autodesk.Revit.DB.XYZ temp = lines.get_Item(0).GetEndPoint(1);
         Curve temCurve = lines.get_Item(0);

         Profile.Append(temCurve);

         while (Profile.Size != lines.Size)
         {

            temCurve = GetNext(lines, temp, temCurve);

            if (Math.Abs(temp.X - temCurve.GetEndPoint(0).X) < PRECISION
                && Math.Abs(temp.Y - temCurve.GetEndPoint(0).Y) < PRECISION)
            {
               temp = temCurve.GetEndPoint(1);
            }
            else
            {
               temp = temCurve.GetEndPoint(0);
            }

            Profile.Append(temCurve);
         }

         if (Math.Abs(temp.X - lines.get_Item(0).GetEndPoint(0).X) > PRECISION
             || Math.Abs(temp.Y - lines.get_Item(0).GetEndPoint(0).Y) > PRECISION
             || Math.Abs(temp.Z - lines.get_Item(0).GetEndPoint(0).Z) > PRECISION)
         {
            throw new InvalidOperationException("The selected walls should be closed.");
         }
      }

      /// <summary>
      /// Get the connected curve for current curve
      /// </summary>
      /// <param name="profile">a closed outline made by the selection of walls</param>
      /// <param name="connected">current curve's end point</param>
      /// <param name="line">current curve</param>
      /// <returns>a appropriate curve for generate floor</returns>
      private Curve GetNext(CurveArray profile, Autodesk.Revit.DB.XYZ connected, Curve line)
      {
         foreach (Curve c in profile)
         {
            if (c.Equals(line))
            {
               continue;
            }
            if ((Math.Abs(c.GetEndPoint(0).X - line.GetEndPoint(1).X) < PRECISION && Math.Abs(c.GetEndPoint(0).Y - line.GetEndPoint(1).Y) < PRECISION && Math.Abs(c.GetEndPoint(0).Z - line.GetEndPoint(1).Z) < PRECISION)
                && (Math.Abs(c.GetEndPoint(1).X - line.GetEndPoint(0).X) < PRECISION && Math.Abs(c.GetEndPoint(1).Y - line.GetEndPoint(0).Y) < PRECISION && Math.Abs(c.GetEndPoint(1).Z - line.GetEndPoint(0).Z) < PRECISION)
                && 2 != profile.Size)
            {
               continue;
            }

            if (Math.Abs(c.GetEndPoint(0).X - connected.X) < PRECISION && Math.Abs(c.GetEndPoint(0).Y - connected.Y) < PRECISION && Math.Abs(c.GetEndPoint(0).Z - connected.Z) < PRECISION)
            {
               return c;
            }
            else if (Math.Abs(c.GetEndPoint(1).X - connected.X) < PRECISION && Math.Abs(c.GetEndPoint(1).Y - connected.Y) < PRECISION && Math.Abs(c.GetEndPoint(1).Z - connected.Z) < PRECISION)
            {
               if (c.GetType().Name.Equals("Line"))
               {
                  Autodesk.Revit.DB.XYZ start = c.GetEndPoint(1);
                  Autodesk.Revit.DB.XYZ end = c.GetEndPoint(0);
                  return Line.CreateBound(start, end);
               }
               else if (c.GetType().Name.Equals("Arc"))
               {
                  int size = c.Tessellate().Count;
                  Autodesk.Revit.DB.XYZ start = c.Tessellate()[0];
                  Autodesk.Revit.DB.XYZ middle = c.Tessellate()[size / 2];
                  Autodesk.Revit.DB.XYZ end = c.Tessellate()[size];

                  return Arc.Create(start, end, middle);
               }
            }
         }

         throw new InvalidOperationException("The selected walls should be closed.");
      }
   }
}

GenerateFloorForm.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.GenerateFloor.CS
{
    partial class GenerateFloorForm
    {
        /// <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.previewGroupBox = new System.Windows.Forms.GroupBox();
            this.previewPictureBox = new System.Windows.Forms.PictureBox();
            this.floorTypesComboBox = new System.Windows.Forms.ComboBox();
            this.structuralCheckBox = new System.Windows.Forms.CheckBox();
            this.OK = new System.Windows.Forms.Button();
            this.Cancel = new System.Windows.Forms.Button();
            this.floorTypeLabel = new System.Windows.Forms.Label();
            this.previewGroupBox.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
            this.SuspendLayout();
            // 
            // previewGroupBox
            // 
            this.previewGroupBox.Controls.Add(this.previewPictureBox);
            this.previewGroupBox.Location = new System.Drawing.Point(12, 12);
            this.previewGroupBox.Name = "previewGroupBox";
            this.previewGroupBox.Size = new System.Drawing.Size(268, 242);
            this.previewGroupBox.TabIndex = 0;
            this.previewGroupBox.TabStop = false;
            this.previewGroupBox.Text = "Preview";
            // 
            // previewPictureBox
            // 
            this.previewPictureBox.BackColor = System.Drawing.SystemColors.ControlText;
            this.previewPictureBox.Location = new System.Drawing.Point(6, 19);
            this.previewPictureBox.Name = "previewPictureBox";
            this.previewPictureBox.Size = new System.Drawing.Size(256, 208);
            this.previewPictureBox.TabIndex = 0;
            this.previewPictureBox.TabStop = false;
            this.previewPictureBox.Paint += new System.Windows.Forms.PaintEventHandler(this.previewPictureBox_Paint);
            // 
            // floorTypesComboBox
            // 
            this.floorTypesComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.floorTypesComboBox.FormattingEnabled = true;
            this.floorTypesComboBox.Location = new System.Drawing.Point(295, 52);
            this.floorTypesComboBox.Name = "floorTypesComboBox";
            this.floorTypesComboBox.Size = new System.Drawing.Size(237, 21);
            this.floorTypesComboBox.TabIndex = 1;
            this.floorTypesComboBox.SelectionChangeCommitted += new System.EventHandler(this.floorTypesComboBox_SelectionChangeCommitted);
            // 
            // structuralCheckBox
            // 
            this.structuralCheckBox.AutoSize = true;
            this.structuralCheckBox.Checked = true;
            this.structuralCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
            this.structuralCheckBox.Location = new System.Drawing.Point(295, 92);
            this.structuralCheckBox.Name = "structuralCheckBox";
            this.structuralCheckBox.Size = new System.Drawing.Size(71, 17);
            this.structuralCheckBox.TabIndex = 2;
            this.structuralCheckBox.Text = "Structural";
            this.structuralCheckBox.UseVisualStyleBackColor = true;
            this.structuralCheckBox.CheckedChanged += new System.EventHandler(this.structralCheckBox_CheckedChanged);
            // 
            // OK
            // 
            this.OK.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.OK.Location = new System.Drawing.Point(376, 244);
            this.OK.Name = "OK";
            this.OK.Size = new System.Drawing.Size(75, 23);
            this.OK.TabIndex = 3;
            this.OK.Text = "&OK";
            this.OK.UseVisualStyleBackColor = true;
            // 
            // Cancel
            // 
            this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Cancel.Location = new System.Drawing.Point(457, 244);
            this.Cancel.Name = "Cancel";
            this.Cancel.Size = new System.Drawing.Size(75, 23);
            this.Cancel.TabIndex = 3;
            this.Cancel.Text = "&Cancel";
            this.Cancel.UseVisualStyleBackColor = true;
            // 
            // floorTypeLabel
            // 
            this.floorTypeLabel.AutoSize = true;
            this.floorTypeLabel.Location = new System.Drawing.Point(292, 22);
            this.floorTypeLabel.Name = "floorTypeLabel";
            this.floorTypeLabel.Size = new System.Drawing.Size(62, 13);
            this.floorTypeLabel.TabIndex = 4;
            this.floorTypeLabel.Text = "Floor Types";
            // 
            // GenerateFloorForm
            // 
            this.AcceptButton = this.OK;
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.CancelButton = this.Cancel;
            this.ClientSize = new System.Drawing.Size(544, 279);
            this.Controls.Add(this.floorTypeLabel);
            this.Controls.Add(this.Cancel);
            this.Controls.Add(this.OK);
            this.Controls.Add(this.structuralCheckBox);
            this.Controls.Add(this.floorTypesComboBox);
            this.Controls.Add(this.previewGroupBox);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "GenerateFloorForm";
            this.ShowInTaskbar = false;
            this.Text = "Generate Floor";
            this.Load += new System.EventHandler(this.GenerateFloorForm_Load);
            this.previewGroupBox.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.GroupBox previewGroupBox;
        private System.Windows.Forms.PictureBox previewPictureBox;
        private System.Windows.Forms.ComboBox floorTypesComboBox;
        private System.Windows.Forms.CheckBox structuralCheckBox;
        private System.Windows.Forms.Button OK;
        private System.Windows.Forms.Button Cancel;
        private System.Windows.Forms.Label floorTypeLabel;
    }
}