using System; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using System.Diagnostics; using System.Collections.Generic; using System.Windows.Forms; using Autodesk.Revit.UI.Selection; //using SpinKler; using System.Drawing; using System.IO; //using System.Windows.Media; // WindowsBase //using System.Windows.Media.Imaging; // PresentationCore using Size = System.Drawing.Size; using KDCS.Utils; using View = Autodesk.Revit.DB.View; using Autodesk.Revit.DB.Structure; using KMBIM.Revit.Tools; namespace KMBIM { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class CmdSprinKler : IExternalCommand { UIApplication m_application; Autodesk.Revit.Creation.ItemFactoryBase m_CreationBase; Autodesk.Revit.Creation.Application creApp; UIDocument m_document; Autodesk.Revit.DB.Document doc; Autodesk.Revit.ApplicationServices.Application app; FamilySymbol INSERTSB; public double m_PlaneOffset = 0; public const double PI = 3.14159265358; public Autodesk.Revit.UI.ExternalCommandData m_revit; public double ksv = 2300; //2300을 pit로 변환해놓은값 public int workPlane_Idx = 0; public Autodesk.Revit.UI.Result Execute(ExternalCommandData revit, ref string message, ElementSet elements) { if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded; m_application = revit.Application; m_document = m_application.ActiveUIDocument; doc = m_document.Document; app = doc.Application; if (m_document.Document.IsFamilyDocument) m_CreationBase = m_document.Document.FamilyCreate; else m_CreationBase = m_document.Document.Create; try { /* FilteredElementCollector collector = new FilteredElementCollector(revit.Application.ActiveUIDocument.Document); Level level = collector.OfClass(typeof(Level)).FirstElement() as Level; */ /* FilteredElementCollector collector = new FilteredElementCollector(m_document.Document); collector.WherePasses(new ElementClassFilter(typeof(Level))); var elements33 = from element in collector where element.Name == m_document.ActiveView.Name select element; Level level = elements33.Cast().ElementAt(0);*/ m_revit = revit; Level level = doc.ActiveView.GenLevel; FormSprinKler aaaa = new FormSprinKler(); aaaa.revit = m_revit; // 일단 레지스트리 값을가져온다. if (aaaa.ShowDialog() == DialogResult.OK) { if(aaaa.Rad_Idx == 1)//천장 배치 { INSERTSB = aaaa.insertsb; SprinKler_Ceiling(revit.Application.ActiveUIDocument.Document, level); } else if(aaaa.Rad_Idx == 2)//작업 기준면에 배치 { INSERTSB = aaaa.insertsb; m_PlaneOffset = aaaa.m_Offset; Sprinkler_WorkPlane(revit.Application.ActiveUIDocument.Document, level, aaaa.str_Workplane); } //if (aaaa.RTcode == 1)//작업 기준면에 배치 //{ // INSERTSB = aaaa.insertsb; // m_PlaneOffset = aaaa.m_Offset; // Sprinkler_WorkPlane(revit.Application.ActiveUIDocument.Document, level); //} //else if (aaaa.RTcode == 2)//현재 레벨에 배치 //{ // //SprayRadius();//살수반경 // // //} //else if (aaaa.RTcode == 3)//천장 배치 //{ // INSERTSB = aaaa.insertsb; // SprinKler_Ceiling(revit.Application.ActiveUIDocument.Document, level); //} } else { return Autodesk.Revit.UI.Result.Succeeded; } } catch (Exception e) { //message = e.Message; return Autodesk.Revit.UI.Result.Failed; } return Autodesk.Revit.UI.Result.Succeeded; } //현재 레벨에 배치 public void Sprinkler_CurrentLevel(Document document, Level level) { XYZ vc1, vc2; double startAng = 0.0, endAng = Math.PI * 2; SketchPlane sketchPlane; Level level2; string m_bname, stmp; XYZ p1 = new XYZ(); XYZ p2 = new XYZ(); XYZ p3 = new XYZ(); XYZ inpt = new XYZ(); double xdst = (double)0, ydst = (double)0, distx = (double)0, disty = (double)0, xangle = (double)0, yangle = (double)0; int i, j, xcnt, ycnt; ObjectSnapTypes snapTypes = ObjectSnapTypes.Centers | ObjectSnapTypes.Endpoints | ObjectSnapTypes.Intersections | ObjectSnapTypes.Midpoints | ObjectSnapTypes.Nearest | ObjectSnapTypes.WorkPlaneGrid | ObjectSnapTypes.Points | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Tangents; p1 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "기준점"); p2 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "첫번째 구석"); p3 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "두번째 구석"); double ang = 45 / 180.0 * PI; ydst = 2 * ksv * System.Math.Sin(ang); xdst = 2 * ksv * System.Math.Cos(ang); //각도 yangle = p1.AngleTo(p3); xangle = p1.AngleTo(p2); //거리 disty = Unit.FeetToMM(p1.DistanceTo(p3)); distx = Unit.FeetToMM(p1.DistanceTo(p2)); //헤드수량 ycnt = Convert.ToInt32(disty / ydst); xcnt = Convert.ToInt32(distx / xdst); //검사후 재 계산 bool flg = false; if (distx > xcnt * xdst) { xcnt += 1; xdst = distx / xcnt; ydst = disty / ycnt; flg = true; } if (disty > ycnt * ydst) { ycnt += 1; xdst = distx / xcnt; ydst = disty / ycnt; } ydst = disty / ycnt; xdst = distx / xcnt; //조건 변경 대화상자 Radius dlg = new Radius(); //dlg.txt_radius.Text = ((int)(ksv / 0.00328)).ToString(); dlg.txt_radius.Text = ksv.ToString(); dlg.txt_length1.Text = Math.Floor(distx).ToString(); dlg.txt_cnt1.Text = xcnt.ToString(); dlg.txt_length2.Text = Math.Floor(disty).ToString(); dlg.txt_cnt2.Text = ycnt.ToString(); dlg.m_xdst = xdst; dlg.m_ydst = ydst; if (dlg.ShowDialog() == DialogResult.OK) { //ksv = Convert.ToDouble(dlg.txt_radius.Text) * 0.00328; xcnt = Convert.ToInt32(dlg.txt_cnt1.Text); ycnt = Convert.ToInt32(dlg.txt_cnt2.Text); ydst = Unit.MMToFeet(dlg.m_ydst); xdst = Unit.MMToFeet(dlg.m_xdst); //ydst = dlg.m_ydst; //xdst = dlg.m_xdst; } else return; XYZ vector1 = p2 - p1; XYZ vector2 = p3 - p1; vc1 = vector1.Normalize(); vc2 = vector2.Normalize(); p1 = p1 + vc1 * (xdst / 2.0); p1 = p1 + vc2 * (ydst / 2.0); //현재 참조면 생성하기. //SketchPlane plane = CreateSketchPlane(); using (Transaction trans = new Transaction(doc)) { trans.Start("start"); for (i = 0; i < xcnt; i++) { inpt = p1 + vc1 * (xdst * i); for (j = 0; j < ycnt; j++) { if (null != INSERTSB) { //2020-10-22 스프링클러 간격띄우기,레벨참조하여 생성되도록 수정. FamilyInstance family = document.Create.NewFamilyInstance(level.GetPlaneReference(), inpt, inpt, INSERTSB); Parameter param = family.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); param.Set(Unit.MMToFeet(m_PlaneOffset)); } else throw new Exception("No column types found."); inpt = inpt + vc2 * ydst; } } trans.Commit(); } } //작업 기준면에 배치 public void Sprinkler_WorkPlane(Autodesk.Revit.DB.Document document, Level level,string str_workPlane) { XYZ vc1, vc2; double startAng = 0.0, endAng = Math.PI * 2; SketchPlane sketchPlane; Level level2; string m_bname, stmp; XYZ p1 = new XYZ(); XYZ p2 = new XYZ(); XYZ p3 = new XYZ(); XYZ inpt = new XYZ(); double xdst = (double)0, ydst = (double)0, distx = (double)0, disty = (double)0, xangle = (double)0, yangle = (double)0; int i, j, xcnt, ycnt; //FilteredElementCollector collector = new FilteredElementCollector(document).OfClass(typeof(SketchPlane)); //ICollection elemIDLst = collector.ToElements(); SketchPlane CurskPlane = doc.ActiveView.SketchPlane; SketchPlane skPlane = null; try { Level WorkLevel = null; ReferencePlane referPlane = null; //작업 기준면 가져오기 IList levelLst = new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements(); IList referPlaneLst = new FilteredElementCollector(doc).OfClass(typeof(ReferencePlane)).ToElements(); foreach (Element elem in levelLst) { Level lvl = elem as Level; if (lvl.Name == str_workPlane) WorkLevel = lvl; } foreach (Element elem in referPlaneLst) { ReferencePlane refPlane = elem as ReferencePlane; if (refPlane.Name == str_workPlane) referPlane = refPlane; } using (Transaction trans = new Transaction(doc)) { trans.Start("start"); if (CurskPlane == null) { Plane plane = Plane.CreateByNormalAndOrigin( document.ActiveView.ViewDirection, document.ActiveView.Origin); skPlane = SketchPlane.Create(document, plane); Level lev = document.ActiveView.GenLevel; skPlane.Name = lev.Name + " - 스프링클러"; //skPlane.get_Parameter() document.ActiveView.SketchPlane = skPlane; document.ActiveView.ShowActiveWorkPlane(); doc.Regenerate(); } else { //현재 작업기준면 그리드 on document.ActiveView.ShowActiveWorkPlane(); } trans.Commit(); } ObjectSnapTypes snapTypes = ObjectSnapTypes.Centers | ObjectSnapTypes.Endpoints | ObjectSnapTypes.Intersections | ObjectSnapTypes.Midpoints | ObjectSnapTypes.Nearest | ObjectSnapTypes.WorkPlaneGrid | ObjectSnapTypes.Points | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Tangents; p1 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "기준점"); p2 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "첫번째 구석"); p3 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "두번째 구석"); //p1 = m_revit.Application.ActiveUIDocument.Selection.PickPoint("기준점"); //p2 = m_revit.Application.ActiveUIDocument.Selection.PickPoint( "첫번째 구석"); //p3 = m_revit.Application.ActiveUIDocument.Selection.PickPoint( "두번째 구석"); double ang = 45 / 180.0 * PI; ydst = 2 * ksv * System.Math.Sin(ang); xdst = 2 * ksv * System.Math.Cos(ang); //각도 yangle = p1.AngleTo(p3); xangle = p1.AngleTo(p2); //거리 disty = Unit.FeetToMM(p1.DistanceTo(p3)); distx = Unit.FeetToMM(p1.DistanceTo(p2)); //헤드수량 ycnt = Convert.ToInt32(disty / ydst); xcnt = Convert.ToInt32(distx / xdst); //검사후 재 계산 bool flg = false; if (distx > xcnt * xdst) { xcnt += 1; xdst = distx / xcnt; ydst = disty / ycnt; flg = true; } if (disty > ycnt * ydst) { ycnt += 1; xdst = distx / xcnt; ydst = disty / ycnt; } ydst = disty / ycnt; xdst = distx / xcnt; //조건 변경 대화상자 Radius dlg = new Radius(); //dlg.txt_radius.Text = ((int)(ksv / 0.00328)).ToString(); dlg.txt_radius.Text = ksv.ToString(); dlg.txt_length1.Text = Math.Floor(distx).ToString(); dlg.txt_cnt1.Text = xcnt.ToString(); dlg.txt_length2.Text = Math.Floor(disty).ToString(); dlg.txt_cnt2.Text = ycnt.ToString(); dlg.m_xdst = xdst; dlg.m_ydst = ydst; if (dlg.ShowDialog() == DialogResult.OK) { //ksv = Convert.ToDouble(dlg.txt_radius.Text) * 0.00328; xcnt = Convert.ToInt32(dlg.txt_cnt1.Text); ycnt = Convert.ToInt32(dlg.txt_cnt2.Text); ydst = Unit.MMToFeet(dlg.m_ydst); xdst = Unit.MMToFeet(dlg.m_xdst); //ydst = dlg.m_ydst; //xdst = dlg.m_xdst; } else { using(Transaction trans = new Transaction(doc)) { trans.Start("gride_delete"); document.ActiveView.HideActiveWorkPlane(); trans.Commit(); } return; } XYZ vector1 = p2 - p1; XYZ vector2 = p3 - p1; vc1 = vector1.Normalize(); vc2 = vector2.Normalize(); p1 = p1 + vc1 * (xdst / 2.0); p1 = p1 + vc2 * (ydst / 2.0); //현재 참조면 생성하기. //SketchPlane plane = CreateSketchPlane(); using (Transaction trans = new Transaction(doc)) { trans.Start("Create"); for (i = 0; i < xcnt; i++) { inpt = p1 + vc1 * (xdst * i); for (j = 0; j < ycnt; j++) { if (null != INSERTSB) { FamilyInstance family = null; if (WorkLevel != null) family = document.Create.NewFamilyInstance(WorkLevel.GetPlaneReference(), inpt, inpt, INSERTSB); else if (referPlane != null) family = document.Create.NewFamilyInstance(referPlane.GetReference(), inpt, inpt, INSERTSB); //2020-10-22 스프링클러 간격띄우기,레벨참조하여 생성되도록 수정 //FamilyInstance family = document.Create.NewFamilyInstance(level.GetPlaneReference(), inpt, inpt, INSERTSB); //FamilyInstance family = document.Create.NewFamilyInstance(WorkPlane.GetPlaneReference(), inpt, inpt, INSERTSB); //FamilyInstance family = document.Create.NewFamilyInstance(inpt,INSERTSB,level,StructuralType.NonStructural); Parameter param = family.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); param.Set(Unit.MMToFeet(m_PlaneOffset)); } else throw new Exception("No column types found."); inpt = inpt + vc2 * ydst; } } //현재 작업기준면 그리드 삭제. doc.Regenerate(); document.ActiveView.HideActiveWorkPlane(); trans.Commit(); } } catch (Exception e) { using (Transaction trans = new Transaction(doc)) { trans.Start("Hide"); document.ActiveView.HideActiveWorkPlane(); trans.Commit(); } //MessageBox.Show("" + e); } //m_document.Document.ActiveView.SketchPlane = plane; //m_document.Document.ActiveView.HideActiveWorkPlane(); } //천장 배치 public void SprinKler_Ceiling(Autodesk.Revit.DB.Document document, Level level) { XYZ vc1, vc2; XYZ p1 = new XYZ(); XYZ p2 = new XYZ(); XYZ p3 = new XYZ(); XYZ inpt = new XYZ(); double xdst = (double)0, ydst = (double)0, distx = (double)0, disty = (double)0, xangle = (double)0, yangle = (double)0; int i, j, xcnt, ycnt; bool CeilingTF = false; WorksetId asdf = m_document.Document.ActiveView.WorksetId; UIDocument uidoc = new UIDocument(document); //ISelectionFilter selFilter = new CeilingSelectionFilter(); try { Face: //ObjectType objtype = ObjectType.Face | ObjectType.LinkedElement; ObjectType objtype = ObjectType.Face; Reference refs = m_revit.Application.ActiveUIDocument.Selection.PickObject(objtype, "작업면을 선택하세요."); ElementId TmpElemID = refs.ElementId; Element TmpElement = document.GetElement(refs.ElementId); //RevitLinkInstance rvtInst = TmpElement as RevitLinkInstance; // //foreach (Document d in app.Documents) //{ // if (d.IsLinked) // { // FilteredElementCollector ceilings = new FilteredElementCollector(d).OfClass(typeof(Ceiling)); // // foreach (Element e in ceilings) // { // Ceiling ceil = e as Ceiling; // Parameter param = ceil.get_Parameter(BuiltInParameter.CEILING_HEIGHTABOVELEVEL_PARAM); // double hgt = param.AsDouble(); // double mm_hgt = Unit.FeetToMM(hgt); // MessageBox.Show("" + e.Name + "\n" + e.Id.IntegerValue); // } // } //} if (TmpElement.Category.Name == "Ceilings" || TmpElement.Category.Name == "천장") CeilingTF = true; if (CeilingTF == false) { MessageBox.Show("선택하신 면이 천장이 아닙니다. 다시 선택하세요."); goto Face; } List ttt = Util.GetFacesAll(m_revit.Application.ActiveUIDocument, TmpElement); Face face = ttt[1]; if (m_revit.Application.ActiveUIDocument.ActiveView.SketchPlane == null) { MessageBox.Show("Work Plane을 설정한 후 시도 하십시오."); return; } ObjectSnapTypes snapTypes = ObjectSnapTypes.Centers | ObjectSnapTypes.Endpoints | ObjectSnapTypes.Intersections | ObjectSnapTypes.Midpoints | ObjectSnapTypes.Nearest | ObjectSnapTypes.WorkPlaneGrid | ObjectSnapTypes.Points | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Tangents; p1 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "기준점"); p2 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "첫번째 구석"); p3 = m_revit.Application.ActiveUIDocument.Selection.PickPoint(snapTypes, "두번째 구석"); double ang = 45 / 180.0 * PI; ydst = 2 * ksv * Math.Sin(ang); xdst = 2 * ksv * Math.Cos(ang); //각도 xangle = p1.AngleTo(p2); yangle = p1.AngleTo(p3); //거리 disty = Unit.FeetToMM(p1.DistanceTo(p3)); distx = Unit.FeetToMM(p1.DistanceTo(p2)); //헤드수량 xcnt = Convert.ToInt32(distx / xdst); ycnt = Convert.ToInt32(disty / ydst); //검사후 재 계산 bool flg = false; if (distx > xcnt * xdst) { //면적에 꽉 차는가? xcnt += 1; xdst = distx / xcnt; ydst = disty / ycnt;//System.Math.Sqrt(ksv * ksv - System.Math.Pow(0.5 * xdst, 2.0)) * 2.0; flg = true; } if (disty > ycnt * ydst) { ycnt += 1; ydst = disty / ycnt; xdst = distx / xcnt; //if (!flg) xdst = System.Math.Sqrt(ksv * ksv - System.Math.Pow(0.5 * ydst, 2.0)) * 2.0; } ydst = disty / ycnt; xdst = distx / xcnt; //초건 변경 대화상자 Radius dlg = new Radius(); dlg.txt_radius.Text = ksv.ToString(); dlg.txt_length1.Text = Math.Floor(distx).ToString(); dlg.txt_cnt1.Text = xcnt.ToString(); dlg.txt_length2.Text = Math.Floor(disty).ToString(); dlg.txt_cnt2.Text = ycnt.ToString(); dlg.m_xdst = xdst; dlg.m_ydst = ydst; if (dlg.ShowDialog() == DialogResult.OK) { //ksv = Convert.ToDouble(dlg.txt_radius.Text) * 0.00328; xcnt = Convert.ToInt32(dlg.txt_cnt1.Text); ycnt = Convert.ToInt32(dlg.txt_cnt2.Text); ydst = Unit.MMToFeet(dlg.m_ydst); xdst = Unit.MMToFeet(dlg.m_xdst); } else return; XYZ vector1 = p2 - p1; XYZ vector2 = p3 - p1; vc1 = vector1.Normalize(); vc2 = vector2.Normalize(); p1 = p1 + vc1 * (xdst / 2.0); p1 = p1 + vc2 * (ydst / 2.0); using (Transaction trans = new Transaction(doc)) { trans.Start("Start"); for (i = 0; i < xcnt; i++) { inpt = p1 + vc1 * (xdst * i); for (j = 0; j < ycnt; j++) { if (null != INSERTSB) { //document.Create.NewFamilyInstance(face, inpt, inpt, INSERTSB); //2021-02-02 스프링클러 간격띄우기,레벨참조하여 생성되도록 수정 FamilyInstance family = document.Create.NewFamilyInstance(inpt, INSERTSB, level, StructuralType.NonStructural); Parameter param = family.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM); param.Set(Unit.MMToFeet(m_PlaneOffset)); } else { throw new Exception("No column types found."); } inpt = inpt + vc2 * ydst; } } trans.Commit(); } } catch { } } internal SketchPlane CreateSketchPlane() { Autodesk.Revit.DB.View view = doc.ActiveView; Plane geometryPlane = view.SketchPlane.GetPlane(); //Plane geometryPlane = m_application.Application.Create.NewPlane(normal, origin); Transaction createSketchPlane = new Transaction(m_document.Document, "Create a sketch plane."); createSketchPlane.Start(); SketchPlane plane = SketchPlane.Create(m_document.Document, geometryPlane); m_document.Document.ActiveView.SketchPlane = plane; //m_document.Document.ActiveView.ShowActiveWorkPlane(); createSketchPlane.Commit(); return plane; } public void SprayRadius() { Autodesk.Revit.DB.View view = doc.ActiveView; double radius = 2300 * 0.00328; IList Elementlist = m_revit.Application.ActiveUIDocument.Selection.PickElementsByRectangle(); for (int i = 0; i < Elementlist.Count; i++) { if (Elementlist[i].Category.Name == "Sprinklers") { Autodesk.Revit.DB.LocationPoint asdf = Elementlist[i].Location as Autodesk.Revit.DB.LocationPoint; Plane pp = m_revit.Application.ActiveUIDocument.Document.ActiveView.SketchPlane.GetPlane(); Plane plane = view.SketchPlane.GetPlane(); //Plane plane = m_revit.Application.Application.Create.NewPlane(pp.Origin, asdf.Point); XYZ normal = XYZ.BasisZ; SketchPlane sketchPlane1 = SketchPlane.Create(m_document.Document, plane); Arc arc1 = Arc.Create(plane, radius, 0.0, Math.PI * 2); ModelCurve TmpCurve = m_document.Document.Create.NewModelCurve(arc1, m_revit.Application.ActiveUIDocument.Document.ActiveView.SketchPlane); } } } public void MakePreView(FamilySymbol sb) { ElementId typeId = sb.GetTypeId(); ElementType type = m_document.Document.GetElement(typeId) as ElementType; Size imgSize = new Size(200, 200); Bitmap image = type.GetPreviewImage(imgSize); string filename = "a.jpg"; FileStream file = new FileStream(filename, FileMode.Create, FileAccess.Write); file.Close(); Process.Start(filename); } } public class CeilingSelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; if (element.Category.Name == "Ceilings") { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } } }