簡單得Revit二次開發-波導線拆分
阿新 • • 發佈:2021-07-16
波導線拆分(基於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] 聯絡開發事宜.