1. 程式人生 > 其它 >簡單得Revit二次開發-波導線拆分

簡單得Revit二次開發-波導線拆分

波導線拆分(基於Revit2019 API)

`using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; using System.Windows.Forms; using Form = System.Windows.Forms.Form;

namespace Boundary { [Transaction(TransactionMode.Manual)] public class LoopBoundary : IExternalCommand { private UIDocument uidoc; private Document currentDocument; private Material currentMat; private PartMaker partMaker;

    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        uidoc = commandData.Application.ActiveUIDocument;
        currentDocument = uidoc.Document;
        partMaker = null;
        currentMat = null;
        message =
        Trans("boundary",
                      () =>
                      {
                          var frm = new DataInput(GetMaterials());
                          var dr = frm.ShowDialog();
                          if (dr != System.Windows.Forms.DialogResult.OK) return null;
                          currentMat = frm.Material;
                          var floor = GetFloor();
                          if (floor == null) return null;
                          var face = GetFace(floor);
                          if (face == null) return "獲取 波導線錯誤";

                          if (!PartUtils.AreElementsValidForCreateParts(currentDocument, new[] { floor.Id }))
                              return "無法為物件建立零件";
                          PartUtils.CreateParts(currentDocument, new[] { floor.Id });
                          currentDocument.Regenerate();

                          var parts = PartUtils.GetAssociatedParts(currentDocument, floor.Id, false, false);
                          if (!PartUtils.ArePartsValidForDivide(currentDocument, parts))
                              return "無法為物件拆分零件";

                          //拆分線 
                          var cvs = GetCurves(face, MmToFt(frm.Length));

                          //拆分平面
                          var p = Plane.CreateByNormalAndOrigin(face.FaceNormal, face.Origin);
                          var sp = SketchPlane.Create(currentDocument, p);
                         
                          partMaker = PartUtils.DivideParts(
                                currentDocument,
                                parts,
                                new List<ElementId>(0),
                                cvs,
                                sp.Id);
                    
                          currentDocument.ActiveView.PartsVisibility = PartsVisibility.ShowPartsOnly;
                          return null;

                      });

        if (!string.IsNullOrEmpty(message)) return Result.Failed;

        SetPartsMat(partMaker);

        return Result.Succeeded;
    }

    private void SetPartsMat(PartMaker pk)
    {
        var filter = new ElementClassFilter(typeof(Part));
        var parts = new FilteredElementCollector(currentDocument)
             .WherePasses(filter)
             .OfType<Part>();

        foreach (var part in parts)
        {
            if (part.PartMaker.Id != pk.Id) continue;
            SetPartMatNoReadOnly(part);
            SetPartMat(part);
        }

    }

    private void SetPartMatNoReadOnly(Part part)
    {
        var original = part.get_Parameter(BuiltInParameter.DPART_MATERIAL_BY_ORIGINAL);
        if (!original.IsReadOnly)
            Trans("original", () => { original.Set(0); });
    }

    private void SetPartMat(Part part)
    {
        var mat = part.get_Parameter(BuiltInParameter.DPART_MATERIAL_ID_PARAM);
        if (!mat.IsReadOnly)
            Trans("mat set", () => { mat.Set(currentMat.Id); });
    }


    private XYZ PointProjectLine(XYZ pt, Line line)
    {
        line.MakeUnbound();
        return line.Project(pt).XYZPoint;
    }


    private string Trans(string tranName, Func<string> func)
    {
        var r = "";
        var trn = new Transaction(currentDocument, tranName);
        using (trn)
        {
            trn.Start();
            r = func();
            trn.Commit();
        }
        return r;
    }

    private void Trans(string tranName, Action action)
    {
        var trn = new Transaction(currentDocument, tranName);
        using (trn)
        {
            trn.Start();
            action();
            trn.Commit();
        }
    }

    private List<Material> GetMaterials()
    {
        var filterByMaterial = new ElementCategoryFilter(BuiltInCategory.OST_Materials);
        var col = new FilteredElementCollector(currentDocument);
        var mats = col.WherePasses(filterByMaterial)
            .OfType<Material>()
            .ToList();
        if (mats.Count > 0)
        {
            return mats;
        }
        throw new ArgumentNullException("無法獲取材質!");
    }

    private Floor GetFloor()
    {
        try
        {
            var fid = uidoc.Selection.PickObject(ObjectType.Element, new FloorSelectionFilter());
            var floor = currentDocument.GetElement(fid.ElementId) as Floor;

            return floor;
        }
        catch
        {
            return null;
        }
    }

    private PlanarFace GetFace(Floor floor)
    {
        var refer = HostObjectUtils.GetTopFaces(floor).FirstOrDefault();
        var planer = floor.GetGeometryObjectFromReference(refer) as PlanarFace;

        return planer;
		}

    private double MmToFt(double mm)
    {
        return UnitUtils.Convert(mm, DisplayUnitType.DUT_MILLIMETERS, DisplayUnitType.DUT_DECIMAL_FEET);
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="floor"></param>
    public List<Curve> GetCurves(PlanarFace planer, double divLen)
    {
        var pts = planer.Triangulate().Vertices;
        foreach (XYZ pt in pts)
        {
            Debug.Print(@"{0},{1}", pt.X, pt.Y);
        }
        var pts1 = pts.Take(pts.Count / 2);
        var pts2 = pts.Skip(pts.Count / 2).Reverse();
        var lst2 = pts2.ToList();
        var lst1 = pts1.ToList();

        var last = pts2.Last();
        lst2.Insert(0, last);
        lst2.RemoveAt(lst2.Count - 1);
        last = lst2.Last();
        lst2.Insert(0, last);
        lst2.RemoveAt(lst2.Count - 1);

        var outs = OrderXyzListByBottomLeft(lst1);
        var inners = OrderXyzListByBottomLeft(lst2);
        var loops = FenChai(inners, outs, divLen);
		
        return Combine(loops, pts);
    }

    private List<XYZ> OrderXyzListByBottomLeft(List<XYZ> pts)
    {
        var r = new List<XYZ>();
        Debug.Print("OrderXyzList");
        var minY = pts.Min(p => p.Y);
        var minX = pts.Where(p => p.Y == minY).Min(pt => pt.X);
        var index = pts.FindIndex(p => p.X == minX && p.Y == minY);
        r = pts.Skip(index).ToList();
        r.AddRange(pts.Take(index));
        return r;
    }

    private List<List<XYZ>> FenChai(List<XYZ> inners, List<XYZ> outers, double divlen)
    {
        var r_inner = new List<XYZ>();
        var r_out = new List<XYZ>();
        inners.Add(inners.First());
        outers.Add(outers.First());
        for (int i = 0; i < inners.Count - 1; i++)
        {
            var p1 = inners[i];
            var p2 = inners[i + 1];
            var outp1 = outers[i];
            var outp2 = outers[i + 1];

            var line_in = Line.CreateBound(p1, p2);
            var line_out = Line.CreateBound(outp1, outp2);

            var direction_in = line_in.Direction;
            var direction_out = line_out.Direction;

            var half = line_in.Length / 2.0;
            var count = (int)(half / divlen);
            count = count * 2;
            var rem_in = half % divlen;

            r_inner.Add(p1);
            r_out.Add(outp1);
            if (rem_in > 1e-9)
            {
                var pt = p1 + direction_in * rem_in;
                r_inner.Add(pt);
                r_out.Add(PointProjectLine(pt, line_out));
            }

            for (int j = 0; j < count; j++)
            {
                var pt = p1 + direction_in * (rem_in + (j + 1) * divlen);
                r_inner.Add(pt);
                r_out.Add(PointProjectLine(pt, line_out));
            }
        }

        r_inner.Add(inners.First());
        r_out.Add(outers.First());
        return new List<List<XYZ>> { r_inner, r_out };
    }

    private List<Curve> Combine(List<List<XYZ>> loops, IList<XYZ> pts)
    {

        var r = new List<Curve>();
        foreach (var loop in loops)
        {
            for (int i = 0; i < loop.Count - 1; i++)
            {
                r.Add(Line.CreateBound(loop[i], loop[i + 1]));
            }
        }

        var loop1 = loops[0];
        var loop2 = loops[1];
        for (int i = 0; i < loop1.Count - 1; i++)
        {
            if (pts.Contains(loop1[i])) continue;
            r.Add(Line.CreateBound(loop1[i], loop2[i]));
        }

        return r;
    }

  

 

    public class FloorSelectionFilter : ISelectionFilter
    {
        public bool AllowElement(Element element)
        {
            if (element.Category == null) return false;
            if (element.Category.Id.IntegerValue != (int)BuiltInCategory.OST_Floors)
                return false;

            var floor = element as Floor;
            if (floor == null) return false;

            var openings = floor.GetDependentElements(new ElementClassFilter(typeof(Opening)));

            return openings.Count > 0;
        }


        public bool AllowReference(Reference reference, XYZ position)
            => false;

    }

    public class DataInput : Form
    {

        /// <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.length_lab = new System.Windows.Forms.Label();
            this.mat_lab = new System.Windows.Forms.Label();
            this.btn_pickFloor = new System.Windows.Forms.Button();
            this.btn_cancel = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.cbox_mats = new System.Windows.Forms.ComboBox();
            this.SuspendLayout();
            // 
            // length_lab
            // 
            this.length_lab.AutoSize = true;
            this.length_lab.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.length_lab.Location = new System.Drawing.Point(19, 39);
            this.length_lab.Name = "length_lab";
            this.length_lab.Size = new System.Drawing.Size(147, 14);
            this.length_lab.TabIndex = 0;
            this.length_lab.Text = "指定波導線長度(mm):";
            // 
            // mat_lab
            // 
            this.mat_lab.AutoSize = true;
            this.mat_lab.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.mat_lab.Location = new System.Drawing.Point(43, 96);
            this.mat_lab.Name = "mat_lab";
            this.mat_lab.Size = new System.Drawing.Size(119, 14);
            this.mat_lab.TabIndex = 0;
            this.mat_lab.Text = "選擇波導線材質:";
            // 
            // btn_pickFloor
            // 
            this.btn_pickFloor.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btn_pickFloor.Location = new System.Drawing.Point(146, 191);
            this.btn_pickFloor.Name = "btn_pickFloor";
            this.btn_pickFloor.Size = new System.Drawing.Size(108, 37);
            this.btn_pickFloor.TabIndex = 1;
            this.btn_pickFloor.Text = "選擇樓板";
            this.btn_pickFloor.UseVisualStyleBackColor = true;
            this.btn_pickFloor.Click += new System.EventHandler(this.btn_pickFloor_Click);
            // 
            // btn_cancel
            // 
            this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.btn_cancel.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btn_cancel.Location = new System.Drawing.Point(271, 191);
            this.btn_cancel.Name = "btn_cancel";
            this.btn_cancel.Size = new System.Drawing.Size(75, 37);
            this.btn_cancel.TabIndex = 1;
            this.btn_cancel.Text = "取消";
            this.btn_cancel.UseVisualStyleBackColor = true;
            // 
            // textBox1
            // 
            this.textBox1.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.textBox1.Location = new System.Drawing.Point(166, 36);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(180, 23);
            this.textBox1.TabIndex = 2;
            this.textBox1.Text = "500";
            this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
            // 
            // cbox_mats
            // 
            this.cbox_mats.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cbox_mats.Font = new System.Drawing.Font("宋體", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.cbox_mats.FormattingEnabled = true;
            this.cbox_mats.ItemHeight = 14;
            this.cbox_mats.Location = new System.Drawing.Point(166, 93);
            this.cbox_mats.Name = "cbox_mats";
            this.cbox_mats.Size = new System.Drawing.Size(180, 22);
            this.cbox_mats.TabIndex = 3;
            // 
            // DataInput
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.CancelButton = this.btn_cancel;
            this.ClientSize = new System.Drawing.Size(383, 264);
            this.Controls.Add(this.cbox_mats);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.btn_cancel);
            this.Controls.Add(this.btn_pickFloor);
            this.Controls.Add(this.mat_lab);
            this.Controls.Add(this.length_lab);
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "DataInput";
            this.Text = "環形波導線";
            this.Load += new System.EventHandler(this.DataInput_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label length_lab;
        private System.Windows.Forms.Label mat_lab;
        private System.Windows.Forms.Button btn_pickFloor;
        private System.Windows.Forms.Button btn_cancel;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.ComboBox cbox_mats;


        public int Length => string.IsNullOrEmpty(textBox1.Text) ? 0 : int.Parse(textBox1.Text);
        public Material Material => cbox_mats.SelectedItem as Material;
        public DataInput(List<Material> lists)
        {
            InitializeComponent();
            cbox_mats.DataSource = lists;
            cbox_mats.DisplayMember = "Name";
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {

            e.Handled = !(char.IsDigit(e.KeyChar) || char.IsControl(e.KeyChar));

        }

        private void DataInput_Load(object sender, EventArgs e)
        {

        }

        private void btn_pickFloor_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            this.Close();
        }
    }
}

} `

本人有多年的CAD開發經驗,獨立完成多個CAD二次開發及Revit二次開發專案。熟悉.net及Asp.net開發技術,和Lisp開發技術。

現在成立了工作室,承接開發專案。結項後提供原始碼及開發文件,有需要的話可以提供發票.

有需求的可以 [email protected] 聯絡開發事宜.