using Autodesk.Revit.DB; using Autodesk.Revit.DB.Mechanical; //using SpinKler; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using KDCS.Utils; using KMBIM.Revit.Tools.Cmd.DuctSize; using KMBIM.Revit.Tools.Properties; using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace KMBIM { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] class Extend2Level : IExternalCommand { UIApplication uiapp; UIDocument uidoc; Autodesk.Revit.DB.Document doc; Autodesk.Revit.Creation.Application creApp; Autodesk.Revit.Creation.Document creDoc; Autodesk.Revit.UI.ExternalCommandData m_commandData; public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { m_commandData = commandData; uiapp = commandData.Application; uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.ApplicationServices.Application app = uiapp.Application; doc = uidoc.Document; creApp = uiapp.Application.Create; creDoc = doc.Create; List m_SelElemLst = new List(); List m_PipeLst = new List(); List m_DuctLst = new List(); List m_VerPipeLst = new List(); List m_VerDuctLst = new List(); try { //if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded; FormExtend2Level dlg = new FormExtend2Level(); dlg.revit = m_commandData; dlg.ShowDialog(); if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded; XYZ PickPoint = null; IList pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), Resources.Ext2Lvl_Select); if (pickrefs != null) { foreach (Reference refer in pickrefs) { PickPoint = refer.GlobalPoint; ElementId tt = refer.ElementId; Element e = doc.GetElement(tt) as Element; //m_SelElemLst.Add(selElem); m_PipeLst.Clear(); m_DuctLst.Clear(); if (e is Pipe) { Pipe pipe = e as Pipe; bool bf = VerticalElem(e); if (bf) m_VerPipeLst.Add(pipe); else m_PipeLst.Add(pipe); } else if (e is Duct) { Duct duct = e as Duct; bool bf = VerticalElem(e); if (bf) m_VerDuctLst.Add(duct); else m_DuctLst.Add(duct); } using (Transaction trans = new Transaction(doc)) { trans.Start("ext"); if (dlg.m_LvlExtend == dlg.m_LvlCurrent) { MessageBox.Show("현재 레벨과 선택한 레벨이 같습니다."); return Result.Failed; } //수직 객체만 레벨 올리기. if (m_VerPipeLst.Count != 0 || m_VerDuctLst.Count != 0) VerExtendLevel(m_VerPipeLst, m_VerDuctLst, dlg.m_LvlExtend, dlg.m_LvlCurrent, dlg.Offset, PickPoint); //수평일 경우 엘보로 레벨 올리기. if (m_PipeLst.Count != 0 || m_DuctLst.Count != 0) HorExtendLevel(m_PipeLst, m_DuctLst, dlg.m_LvlExtend, dlg.m_LvlCurrent, dlg.Offset, PickPoint); trans.Commit(); } } } else return Result.Succeeded; //oldType = IsConnectToElbow(m_SelElemLst[0]); //수평등 커넥터 z값 같은값은 걸러냄. //m_PipeLst = getVerticalElem(m_SelElemLst); //foreach (Element e in m_SelElemLst) //{ // if (e is Pipe) // { // Pipe pipe = e as Pipe; // bool bf = VerticalElem(e); // if (bf) // m_VerPipeLst.Add(pipe); // else // m_PipeLst.Add(pipe); // } // else if (e is Duct) // { // Duct duct = e as Duct; // bool bf = VerticalElem(e); // if (bf) // m_VerDuctLst.Add(duct); // else // m_DuctLst.Add(duct); // } //} //MessageBox.Show("파이프 수직 : " + m_VerPipeLst.Count + "\n파이프 수평 : " + m_PipeLst.Count + "\n덕트 수직 : " + m_VerDuctLst.Count + "\n덕트 수평 : " + m_DuctLst.Count); //using (Transaction trans = new Transaction(doc)) //{ // trans.Start("ext"); // //수직 객체만 레벨 올리기. // if (m_VerPipeLst.Count != 0 || m_VerDuctLst.Count != 0) // VerExtendLevel(m_VerPipeLst, m_VerDuctLst, dlg.m_LvlExtend, dlg.m_LvlCurrent, dlg.Offset); // //수평일 경우 엘보로 레벨 올리기. // if (m_PipeLst.Count != 0 || m_DuctLst.Count != 0) // HorExtendLevel(m_PipeLst, m_DuctLst, dlg.m_LvlExtend, dlg.m_LvlCurrent, dlg.Offset); // trans.Commit(); //} } catch (Autodesk.Revit.Exceptions.ArgumentException) { MessageBox.Show("현재 레벨과 연장할 레벨이 같습니다.","Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return Result.Failed; } //catch (Exception ex) //{ // //MessageBox.Show(ex.ToString()); //} return Result.Succeeded; } public bool VerticalElem(Element Elem) { List resElemLst = new List(); List connectorpts = new List(); if (Elem is Pipe) { Pipe pipe = Elem as Pipe; ConnectorManager connectorManager1 = pipe.ConnectorManager; ConnectorSet connectorSet1 = connectorManager1.Connectors; foreach (Connector con in connectorSet1) { connectorpts.Add(con.Origin); } if (Math.Abs(connectorpts[0].Z - connectorpts[1].Z) < 0.001) return false; else return true; } else if (Elem is Duct) { Duct duct = Elem as Duct; ConnectorManager connectorManager1 = duct.ConnectorManager; ConnectorSet connectorSet1 = connectorManager1.Connectors; foreach (Connector con in connectorSet1) { connectorpts.Add(con.Origin); } if (Math.Abs(connectorpts[0].Z - connectorpts[1].Z) < 0.001) return false; else return true; } return false; } //수직 파이프 리스트, 수직 덕트 리스트, 확장할 레벨, 현재 레벨, 오프셋 public void VerExtendLevel(List VerPipeElemLst, List VerDuctElemLst, string ExtendLevelName, string currentLevelName, double m_Offset, XYZ pickPoint) { UIApplication uiapp = m_commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.DB.Document doc = uidoc.Document; Autodesk.Revit.DB.View view = doc.ActiveView; List ElemList = new List(); Element m_CurLvlElem = null, m_ExtLvlELem = null; Parameter level = view.LookupParameter("Associated Level"); FilteredElementCollector lvlCollector = new FilteredElementCollector(doc); ICollection lvlCollection = lvlCollector.OfClass(typeof(Level)).ToElements(); foreach (Element l in lvlCollection) { Level lvl = l as Level; if (lvl.Name == ExtendLevelName) { //확장 레벨의 Element m_ExtLvlELem = l; } if (lvl.Name == currentLevelName) { //현재 레벨의 Element m_CurLvlElem = l; } } Level m_ExtLevel = m_ExtLvlELem as Level; double d_Ext = m_ExtLevel.Elevation; Level m_CurLevel = m_CurLvlElem as Level; //double d_cur = m_CurLevel.Elevation; double d_offset = Unit.MMToFeet(m_Offset); //DeleteElbow(doc, PipeElemLst); double reshgt = d_Ext + d_offset; PipeStretch(VerPipeElemLst, reshgt); DuctStretch(VerDuctElemLst, reshgt); } //수평 파이프 리스트, 수평 덕트 리스트, 확장할 레벨, 현재 레벨, 오프셋 public void HorExtendLevel(List HorPipeElemLst, List HorDuctElemLst, string ExtendLevelName, string currentLevelName, double m_Offset, XYZ Pickpoint) { UIApplication uiapp = m_commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.DB.Document doc = uidoc.Document; Autodesk.Revit.DB.View view = doc.ActiveView; List ElemList = new List(); Element m_CurLvlElem = null, m_ExtLvlELem = null; Parameter level = view.LookupParameter("Associated Level"); FilteredElementCollector lvlCollector = new FilteredElementCollector(doc); ICollection lvlCollection = lvlCollector.OfClass(typeof(Level)).ToElements(); foreach (Element l in lvlCollection) { Level lvl = l as Level; if (lvl.Name == ExtendLevelName) { //확장 레벨의 Element m_ExtLvlELem = l; } if (lvl.Name == currentLevelName) { //현재 레벨의 Element m_CurLvlElem = l; } } Level m_ExtLevel = m_ExtLvlELem as Level; double d_Ext = m_ExtLevel.Elevation; Level m_CurLevel = m_CurLvlElem as Level; //double d_cur = m_CurLevel.Elevation; //double d_offset = Unit.MMToFeet(m_Offset, DisplayUnitType.DUT_MILLIMETERS); double d_offset = Unit.MMToFeet(m_Offset); //DeleteElbow(doc, PipeElemLst); double reshgt = d_Ext + d_offset; foreach (Pipe pipe in HorPipeElemLst) { //파이프 레벨연장 CreatePipe(pipe, reshgt, Pickpoint); } foreach (Duct duct in HorDuctElemLst) { CreateDuct(duct, reshgt, Pickpoint); } } public bool PipeStretch(List m_list, double hgt) { foreach (Pipe pipe in m_list) { List pipeConLst = Util.GetElementConnectors(pipe); foreach (Connector con in pipeConLst) { //커넥터에 객체가 연결안되었을 때 if (con.IsConnected == false) { Connector OtherCon = Util.GetOtherConnector(con); if (OtherCon != null) { if (con.Origin.Z > OtherCon.Origin.Z) con.Origin = new XYZ(OtherCon.Origin.X, OtherCon.Origin.Y, hgt); else OtherCon.Origin = new XYZ(con.Origin.X, con.Origin.Y, hgt); } } } }//foreach end return true; } public bool DuctStretch(List m_list, double hgt) { foreach (Duct duct in m_list) { List ductConLst = Util.GetElementConnectors(duct); foreach (Connector con in ductConLst) { //커넥터에 객체가 연결안되었을 때 if (con.IsConnected == false) { Connector OtherCon = Util.GetOtherConnector(con); if (OtherCon != null) { if (con.Origin.Z > OtherCon.Origin.Z) con.Origin = new XYZ(OtherCon.Origin.X, OtherCon.Origin.Y, hgt); else OtherCon.Origin = new XYZ(con.Origin.X, con.Origin.Y, hgt); } } } } return true; } public void CreatePipe(Pipe pipe, double Height) { List m_PipeLst = new List(); PipeType pipetype = pipe.PipeType; Level level = pipe.ReferenceLevel; ElementId pipeSysTypeId = pipe.MEPSystem.GetTypeId(); //파이프 끝점 올리기위해 점 찾기 Line pipeLine = (pipe.Location as LocationCurve).Curve as Line; XYZ pipEndpt = pipeLine.GetEndPoint(1); //Util.Pyosi(doc,pipEndpt); Pipe newPipe = null; //ConnectorManager connectorManager = pipe.ConnectorManager; ConnectorSet connectorSet = pipe.ConnectorManager.Connectors; foreach (Connector con in connectorSet) { if (con.IsConnected == false) { //conLst.Add(con); //if (pipEndpt.IsAlmostEqualTo(con.Origin)) //{ XYZ a = new XYZ(con.Origin.X, con.Origin.Y, con.Origin.Z); //Util.Pyosi(doc, a, false); XYZ VerPt = new XYZ(con.Origin.X, con.Origin.Y, Height); //Util.Pyosi(doc,VerPt); //using (Transaction trans = new Transaction(doc)) //{ // trans.Start("CreatePipe"); newPipe = Pipe.Create(doc, pipeSysTypeId, pipetype.Id, level.Id, con.Origin, VerPt); Parameter pipeParam = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM); Connector con1 = newPipe.ConnectorManager.Connectors.Cast().First(); con1.Radius = pipeParam.AsDouble() / 2.0; //ConnectorManager conMngr = newPipe.ConnectorManager; ConnectorSet conSet = newPipe.ConnectorManager.Connectors; foreach (Connector connector in conSet) { if (connector.Origin.IsAlmostEqualTo(con.Origin)) { ElementId oldType = IsConnectToElbow(pipe as Element); FamilyInstance fitting = doc.Create.NewElbowFitting(con, connector); //if (oldType != null) // fitting.ChangeTypeId(oldType); } } // trans.Commit(); //} //} } } } //Pickpoint를 기준으로 가까운 쪽을 연장 public void CreatePipe(Pipe pipe, double Height, XYZ Pickpoint) { List m_PipeLst = new List(); PipeType pipetype = pipe.PipeType; Level level = pipe.ReferenceLevel; ElementId pipeSysTypeId = pipe.MEPSystem.GetTypeId(); //파이프 끝점 올리기위해 점 찾기 Line pipeLine = (pipe.Location as LocationCurve).Curve as Line; XYZ pipEndpt = pipeLine.GetEndPoint(1); //Util.Pyosi(doc,pipEndpt); Pipe newPipe = null; //ConnectorManager connectorManager = pipe.ConnectorManager; ConnectorSet connectorSet = pipe.ConnectorManager.Connectors; List EndpointLst = new List(); foreach (Connector fncon in connectorSet) { XYZ Endpoint = new XYZ(fncon.Origin.X, fncon.Origin.Y, fncon.Origin.Z); EndpointLst.Add(Endpoint); } XYZ Midpoint = Util.Midpoint(EndpointLst[0], EndpointLst[1]); ElementId elbow = IsConnectToElbow(pipe); foreach (Connector con in connectorSet) { XYZ Conpt = new XYZ(con.Origin.X, con.Origin.Y, con.Origin.Z); if (elbow == null) { double pickDist = Conpt.DistanceTo(Pickpoint); double midDist = Conpt.DistanceTo(Midpoint); if (pickDist > midDist) continue; } if (con.IsConnected == false) { //conLst.Add(con); //if (pipEndpt.IsAlmostEqualTo(con.Origin)) //{ XYZ VerPt = new XYZ(con.Origin.X, con.Origin.Y, Height); //Util.Pyosi(doc,VerPt); //using (Transaction trans = new Transaction(doc)) //{ // trans.Start("CreatePipe"); newPipe = Pipe.Create(doc, pipeSysTypeId, pipetype.Id, level.Id, con.Origin, VerPt); Parameter pipeParam = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM); Connector con1 = newPipe.ConnectorManager.Connectors.Cast().First(); con1.Radius = pipeParam.AsDouble() / 2.0; //ConnectorManager conMngr = newPipe.ConnectorManager; ConnectorSet conSet = newPipe.ConnectorManager.Connectors; foreach (Connector connector in conSet) { if (connector.Origin.IsAlmostEqualTo(con.Origin)) { ElementId oldType = IsConnectToElbow(pipe as Element); FamilyInstance fitting = doc.Create.NewElbowFitting(con, connector); //if (oldType != null) // fitting.ChangeTypeId(oldType); } } // trans.Commit(); //} //} } } } public Connector CreateDuct(Duct duct, double Height) { List m_DuctLst = new List(); Connector resCon = null; DuctType ductType = duct.DuctType; Level level = duct.ReferenceLevel; ElementId pipeSysTypeId = duct.MEPSystem.GetTypeId(); //파이프 끝점 올리기위해 점 찾기 //Line ductLine = (duct.Location as LocationCurve).Curve as Line; Duct newDuct = null; ConnectorSet connectorSet = duct.ConnectorManager.Connectors; //덕트 시작 끝점 구하기. //덕트의 시작점을 올리면 덕트의 폭 높이가 반대로 작도되는 현상때문에 비교해야 함. XYZ m_DuctSp = null, m_DuctEp = null; Util.GetStartEndPoint(duct, ref m_DuctSp, ref m_DuctEp); foreach (Connector con in connectorSet) { if (con.IsConnected == false) { XYZ VerPt = new XYZ(con.Origin.X, con.Origin.Y, Height); //Pyosi(con.Origin,0); //Pyosi(m_DuctEp, 0); //newDuct = Duct.Create(doc, pipeSysTypeId, ductType.Id, level.Id, con.Origin, VerPt); newDuct = Duct.Create(doc, pipeSysTypeId, ductType.Id, level.Id, VerPt, con.Origin); Parameter ductParam = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM); Connector con1 = newDuct.ConnectorManager.Connectors.Cast().First(); con1.Width = ductParam.AsDouble(); ductParam = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM); con1.Height = ductParam.AsDouble(); bool Paralell = Util.IsParallel(con1.CoordinateSystem.BasisX, con.CoordinateSystem.BasisX); if (Paralell != true) { //MessageBox.Show("not paralell"); double ang = con1.CoordinateSystem.BasisX.AngleTo(con.CoordinateSystem.BasisX); bool b_rotElem = Util.RotateElement(newDuct, ang); //조정 후 90도로 잘못 꺾일 경우 존재하여 다시한번 조정 con1 = newDuct.ConnectorManager.Connectors.Cast().First(); bool re_Paralell = Util.IsParallel(con1.CoordinateSystem.BasisX, con.CoordinateSystem.BasisX); if (re_Paralell != true) { ang = con1.CoordinateSystem.BasisX.AngleTo(con.CoordinateSystem.BasisX); b_rotElem = Util.RotateElement(newDuct, ang); } } ConnectorSet conSet = newDuct.ConnectorManager.Connectors; //엘보작도 //foreach (Connector connector in conSet) //{ // if (connector.Origin.IsAlmostEqualTo(con.Origin)) // { // ElementId oldType = IsConnectToElbow(duct as Element); // FamilyInstance fitting = doc.Create.NewElbowFitting(con, connector); // //if (oldType != null) // // fitting.ChangeTypeId(oldType); // resCon = connector; // } //} } } return resCon; } //Pickpoint를 기준으로 가까운곳을 연장 public Connector CreateDuct(Duct duct, double Height, XYZ Pickpoint) { List m_DuctLst = new List(); Connector resCon = null; DuctType ductType = duct.DuctType; Level level = duct.ReferenceLevel; ElementId pipeSysTypeId = duct.MEPSystem.GetTypeId(); DuctSizeCmd cmd = new DuctSizeCmd(); //파이프 끝점 올리기위해 점 찾기 //Line ductLine = (duct.Location as LocationCurve).Curve as Line; Duct newDuct = null; ConnectorSet connectorSet = duct.ConnectorManager.Connectors; //덕트 시작 끝점 구하기. //덕트의 시작점을 올리면 덕트의 폭 높이가 반대로 작도되는 현상때문에 비교해야 함. XYZ m_DuctSp = null, m_DuctEp = null; Util.GetStartEndPoint(duct, ref m_DuctSp, ref m_DuctEp); List EndpointLst = new List(); foreach (Connector con in connectorSet) { XYZ Endpoint = new XYZ(con.Origin.X, con.Origin.Y, con.Origin.Z); EndpointLst.Add(Endpoint); } XYZ Midpoint = Util.Midpoint(EndpointLst[0], EndpointLst[1]); ElementId elbow = IsConnectToElbow(duct); foreach (Connector con in connectorSet) { XYZ Conpt = new XYZ(con.Origin.X, con.Origin.Y, con.Origin.Z); if (elbow == null) { double pickDist = Conpt.DistanceTo(Pickpoint); double midDist = Conpt.DistanceTo(Midpoint); if (pickDist > midDist) continue; } if (con.IsConnected == false) { XYZ VerPt = new XYZ(con.Origin.X, con.Origin.Y, Height); //Pyosi(m_DuctEp, 0); //newDuct = Duct.Create(doc, pipeSysTypeId, ductType.Id, level.Id, con.Origin, VerPt); newDuct = Duct.Create(doc, pipeSysTypeId, ductType.Id, level.Id, VerPt, con.Origin); Parameter ductParam = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM); Connector con1 = newDuct.ConnectorManager.Connectors.Cast().First(); con1.Width = ductParam.AsDouble(); ductParam = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM); con1.Height = ductParam.AsDouble(); bool Paralell = Util.IsParallel(con1.CoordinateSystem.BasisX, con.CoordinateSystem.BasisX); if (Paralell != true) { //MessageBox.Show("not paralell"); double ang = con1.CoordinateSystem.BasisX.AngleTo(con.CoordinateSystem.BasisX); bool b_rotElem = Util.RotateElement(newDuct, ang); //조정 후 90도로 잘못 꺾일 경우 존재하여 다시한번 조정 con1 = newDuct.ConnectorManager.Connectors.Cast().First(); bool re_Paralell = Util.IsParallel(con1.CoordinateSystem.BasisX, con.CoordinateSystem.BasisX); if (re_Paralell != true) { ang = con1.CoordinateSystem.BasisX.AngleTo(con.CoordinateSystem.BasisX); b_rotElem = Util.RotateElement(newDuct, ang); } } ConnectorSet conSet = newDuct.ConnectorManager.Connectors; foreach (Connector connector in conSet) { if (connector.Origin.IsAlmostEqualTo(con.Origin)) { ElementId oldType = IsConnectToElbow(duct as Element); FamilyInstance fitting = doc.Create.NewElbowFitting(con, connector); //if (oldType != null) // fitting.ChangeTypeId(oldType); resCon = connector; } } } } return resCon; } //커넥터중 엘보가 있다면 엘보의 타입을 가져옴 public ElementId IsConnectToElbow(Element elem) { ConnectorManager connectorManager; ConnectorSet connectorSet = null; if (elem is Pipe) { Pipe pipe = elem as Pipe; connectorManager = pipe.ConnectorManager; connectorSet = connectorManager.Connectors; } else if (elem is Duct) { Duct duct = elem as Duct; connectorManager = duct.ConnectorManager; connectorSet = connectorManager.Connectors; } foreach (Connector con in connectorSet) { if (con.IsConnected == true) { MEPSystem mepSystem = con.MEPSystem; if (null != mepSystem) { if (con.IsConnected == true) { ConnectorSet conSet = con.AllRefs; ConnectorSetIterator csi = conSet.ForwardIterator(); while (csi.MoveNext()) { Connector connected = csi.Current as Connector; if (null != connected) { if (connected.Owner is FamilyInstance) { FamilyInstance familyInstance = connected.Owner as FamilyInstance; return familyInstance.GetTypeId(); } } } } } } } return null; } public class SelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves || element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } } } }