using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using KMBIM.Revit.Tools; using Autodesk.Revit.UI.Selection; using System.Windows.Forms; using Autodesk.Revit.DB.Mechanical; using System.Diagnostics; using System.Drawing; using KMBIM.Revit.Tools.Utils; using Autodesk.Revit.DB.Plumbing; using KDCS.Utils; using System.IO; using KMBIM.Utils; namespace KMBIM.Revit.Tools.Cmd.DuctSize { /// /// Implements interface IExternalCommand of Revit API. /// [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] [Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)] public class DuctSizeCmd : IExternalCommand { UIApplication m_pUIApp; UIDocument uidoc = null; Document doc = null; MechanicalSystemType ductSystemType = null; DuctType ductType = null; List _added_emement_ids = new List(); public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements) { try { if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded; m_pUIApp = commandData.Application; uidoc = m_pUIApp.ActiveUIDocument; doc = uidoc.Document; Selection sel1 = uidoc.Selection; DefinitionFile informationFile = OpenSharedParameter(); if (null == informationFile) { return Result.Failed; } FilteredElementCollector collectorDuct = new FilteredElementCollector(doc); var ductSystemTypes = collectorDuct.OfClass(typeof(MechanicalSystemType)).ToElements(); foreach (MechanicalSystemType systemType in ductSystemTypes) { if (systemType.SystemClassification == MEPSystemClassification.SupplyAir || systemType.SystemClassification == MEPSystemClassification.ReturnAir) { ductSystemType = systemType; break; } } if (ductSystemType == null) { MessageBox.Show("덕트 시스템유형을 지정할 수 없습니다."); return Result.Failed; } List ductCollection = new FilteredElementCollector(doc) .OfClass(typeof(DuctType)) .OfType() .ToList(); if (ductCollection.Count < 1) { MessageBox.Show("사용 가능한 덕트 유형이 없습니다."); return Result.Failed; } ductType = ductCollection.First(); /* m_pt1 = sel1.PickPoint("시작점 지정"); m_duct = null; ElementId levelId = doc.ActiveView.LevelId; List lstDuctPlaceholder = new List(); FilteredElementCollector collectorDuct = new FilteredElementCollector(doc); var ductSystemTypes = collectorDuct.OfClass(typeof(MechanicalSystemType)).ToElements(); foreach (MechanicalSystemType systemType in ductSystemTypes) { if (systemType.SystemClassification == MEPSystemClassification.SupplyAir || systemType.SystemClassification == MEPSystemClassification.ReturnAir) { ductSystemType = systemType; break; } } if (ductSystemType == null) { MessageBox.Show("덕트 시스템유형을 지정할 수 없습니다."); return Result.Failed; } List ductCollection = new FilteredElementCollector(doc) .OfClass(typeof(DuctType)) .OfType() .ToList(); if (ductCollection.Count < 1) { MessageBox.Show("사용 가능한 덕트 유형이 없습니다."); return Result.Failed; } DuctType ductType = ductCollection.First(); FamilySymbol symbol = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_DetailComponents).OfClass(typeof(FamilySymbol)).Cast().Where(x => x.Name == "kdcs_route").FirstOrDefault(); FamilyInstanceCreator fiCreator = new FamilyInstanceCreator(m_pUIApp); */ /* m_pUIApp.Idling += (s, e) => { System.Drawing.Point ptScreen = getScreenPoint(); m_pt2 = getXYZ(uidoc, ptScreen); if(m_pt1.IsZeroLength()==false && m_pt2.IsZeroLength()==false){ if (m_duct == null) { m_duct = Duct.CreatePlaceholder(doc, ductSystemType.Id, ductType.Id, levelId, m_pt1, m_pt2); } else { } } }; * m_pt2 = sel1.PickPoint("다음점 지정"); m_duct = Duct.CreatePlaceholder(doc, ductSystemType.Id, ductType.Id, levelId, m_pt1, m_pt2); return Result.Succeeded; */ /* var pb = sel1.PickBox(PickBoxStyle.Crossing, "Pick Box: "); ModelCurve visualLine = null; using (TransactionGroup tGroup = new TransactionGroup(doc)) { tGroup.Start(); Redraw: using (Transaction t = new Transaction(doc)) { t.Start("Step 1"); Line line = Line.CreateBound(p1, getP3(uidoc)); Plane geomPlane = Plane.CreateByNormalAndOrigin(doc.ActiveView.ViewDirection, doc.ActiveView.Origin); SketchPlane sketch = SketchPlane.Create(doc, geomPlane); visualLine = doc.Create.NewModelCurve(line, sketch) as ModelCurve; doc.Regenerate(); uidoc.RefreshActiveView(); goto Redraw; t.Commit(); } tGroup.Commit(); } return Result.Succeeded; */ List selIds = new List(); // 선택된 아이디 List visitedIds = new List(); // 방문한 덕트 아이디 uidoc.Selection.SetElementIds(visitedIds); var ductref = uidoc.Selection.PickObject(ObjectType.Element, "주 덕트 대행자 선택"); if (ductref == null) return Result.Failed; Autodesk.Revit.DB.Mechanical.Duct ductMain = doc.GetElement(ductref) as Autodesk.Revit.DB.Mechanical.Duct; if (ductMain == null) return Result.Failed; Autodesk.Revit.DB.Color clr_r = new Autodesk.Revit.DB.Color(255, 0, 0); Autodesk.Revit.DB.Color clr_b = new Autodesk.Revit.DB.Color(0, 0, 255); /* String s2 = string.Empty; foreach (Connector c in ductMain.ConnectorManager.Connectors) { using (TransactionGroup tGroup = new TransactionGroup(doc)) { tGroup.Start("덕트 사이즈 계산"); Util.Pyosi(doc, c.Origin, true, clr_r); MessageBox.Show("M" + c.Origin.ToString()); int j = 1; foreach (Connector c1 in c.AllRefs) { Util.Pyosi(doc, c1.Origin, true, clr_b); s2 = string.Format("R-{0}{1}", j, c1.Origin.ToString()); MessageBox.Show(s2); j++; } MessageBox.Show("계속"); tGroup.RollBack(); } } return Result.Succeeded; */ double m3_per_h = 0.0098096296448581; // 1m3/h = 0.0098096296448581 ft3/s // 개별풍량, 전체풍량 파라미터 준비 InitDuctFlow(ductMain, informationFile, "IndividualFlow"); InitDuctFlow(ductMain, informationFile, "TotalFlow"); // 선택한 덕트에 연결된 모든 덕트 및 부속류 방문 ElementId curId = null; selIds.Add(ductMain.Id); FormDuctSize frmDuctSize = new FormDuctSize(); if (frmDuctSize.ShowDialog() != DialogResult.OK) return Result.Cancelled; while(selIds.Count>0){ curId = selIds.First(); selIds.RemoveAt(0); visitedIds.Add(curId); Element e1 = doc.GetElement(curId); Type e1Type = e1.GetType(); ConnectorManager conMan = null; if (e1Type == typeof(Autodesk.Revit.DB.Mechanical.Duct)) { Autodesk.Revit.DB.Mechanical.Duct duct = e1 as Autodesk.Revit.DB.Mechanical.Duct; conMan = duct.ConnectorManager; } else if (e1Type == typeof(FamilyInstance)) { FamilyInstance fi = e1 as FamilyInstance; if (fi.MEPModel != null) { conMan = fi.MEPModel.ConnectorManager; } } if (conMan != null) { foreach (Connector selfcon in conMan.Connectors) { Connector otherConnector = FindConnectedTo(selfcon); if (otherConnector != null) { if (visitedIds.Contains(otherConnector.Owner.Id) == false) // 방문 이력이 없는 덕트 아이디만 추가 { selIds.Add(otherConnector.Owner.Id); } } } } } List idsAppliedFlow = new List(); // 방문한 덕트 아이디 uidoc.Selection.SetElementIds(visitedIds); visitedIds.Reverse(); using (TransactionGroup tGroup = new TransactionGroup(doc)) { tGroup.Start("덕트 사이즈 계산"); while (visitedIds.Count > 0) { ElementId idDuct = visitedIds.First(); visitedIds.RemoveAt(0); Autodesk.Revit.DB.Mechanical.Duct curDuct = doc.GetElement(idDuct) as Autodesk.Revit.DB.Mechanical.Duct; if (curDuct == null) { continue; } double totFlow = 0d; // 개별풍량 반영 double dblFlow0 = GetIndividualFlow(curDuct); if (Util.fuzzyEqual(dblFlow0, 0) == false) { totFlow += dblFlow0; } // 현재 덕트에 연결된 덕트 if (curDuct.ConnectorManager == null) return Result.Failed; ConnectorManager conManCurDuct = curDuct.ConnectorManager; Line curDuctLine = (curDuct.Location as LocationCurve).Curve as Line; XYZ sp = curDuctLine.GetEndPoint(0); XYZ ep = curDuctLine.GetEndPoint(1); XYZ mp = Util.Midpoint(sp, ep); //Util.Pyosi(doc, mp, true, clr_b); //MessageBox.Show("mp"); Connector conSP = FindConnector(curDuct, sp); Connector conEP = FindConnector(curDuct, ep); Connector conSPOther = FindConnectedTo(conSP); Connector conEPOther = FindConnectedTo(conEP); Autodesk.Revit.DB.Mechanical.Duct ductSPOther = conSPOther!=null?doc.GetElement(conSPOther.Owner.Id) as Autodesk.Revit.DB.Mechanical.Duct: null; Autodesk.Revit.DB.Mechanical.Duct ductEPOther = conEPOther!=null?doc.GetElement(conEPOther.Owner.Id) as Autodesk.Revit.DB.Mechanical.Duct: null; XYZ bp_start=null; XYZ bp_end=null; if (curDuct.Id == ductMain.Id) { bp_start = sp; bp_end = ep; if (ductSPOther!=null && conEPOther == null) { Util.Swap(ref bp_start, ref bp_end); } } else { if (ductEPOther != null) { ElementId eId = idsAppliedFlow.Find(x => x.Equals(ductEPOther.Id)); if (eId != null) { bp_start = sp; bp_end = ep; } else if (ductSPOther == null && conManCurDuct.Connectors.Size == 2) // 엘보-덕트 말단 { SetAirFlowTr(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(curDuct.Id); continue; } else { bp_start = ep; bp_end = sp; } }else if (ductSPOther != null) { ElementId eId = idsAppliedFlow.Find(x => x.Equals(ductSPOther.Id)); if (eId != null) { bp_start = ep; bp_end = sp; } else if (ductEPOther == null && conManCurDuct.Connectors.Size == 2) // 엘보-덕트 말단 { SetAirFlowTr(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(curDuct.Id); continue; } else { bp_start = sp; bp_end = ep; } } else { // 탭->덕트 말단 SetAirFlowTr(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(curDuct.Id); continue; } } // 여기서부터는 덕트 양 끝 커넥터가 연결된 상태 XYZ cur_duct_sp = bp_start; XYZ cur_duct_ep = bp_end; Autodesk.Revit.DB.Color clr_g = new Autodesk.Revit.DB.Color(0, 255, 0); //Util.Pyosi(doc, bp_end, true, clr_g); List sourceConnectors = new List(); List sortedConnectors = new List(); foreach (Connector c in conManCurDuct.Connectors) { // 시작 연결점은 제외 if (c.IsConnected && cur_duct_sp.IsAlmostEqualTo(c.Origin) == false) sourceConnectors.Add(c); } List sortedConnectorPoints = new List(); // 정렬 // 덕트말단 또는 이미 풍량을 반영한 덕트(idsAppliedFlow) 연결점을 기준으로 정렬 if (sourceConnectors.Count > 1) { while (sourceConnectors.Count > 0) { double minDst = Double.MaxValue; Connector closestConnector = null; foreach (Connector c in sourceConnectors) { double dst = bp_start.DistanceTo(c.Origin); if (dst < minDst) { minDst = dst; closestConnector = c; } } sourceConnectors.Remove(closestConnector); // 메인 시작점으로부터 일정 거리 떨어져 있는 커넥터만 처리 if (closestConnector.Origin.DistanceTo(cur_duct_sp) >= 0.164042) { // 5cm = 0.164042ft sortedConnectors.Add(closestConnector); } } sortedConnectors.Reverse(); foreach (Connector c in sortedConnectors) { sortedConnectorPoints.Add(c.Origin); } } else { sortedConnectors.Add(sourceConnectors.First()); sortedConnectorPoints.Add(sourceConnectors.First().Origin); } Duct newDuct = null; // 현재 덕트선의 말단에서 주덕트 방향으로 교차점을 찾아 분할이 필요한 부분은 절단한다. int nTotBranch = sortedConnectorPoints.Count; int nBreak = 0; while (sortedConnectorPoints.Count > 0) { // 가장 멀리 떨어져 있는 연결점부터 처리 XYZ ptThisConnector = sortedConnectorPoints.First(); //Util.Pyosi(doc, ptThisConnector, true); sortedConnectorPoints.RemoveAt(0); Connector thisConnector = FindConnector(curDuct, ptThisConnector); if (thisConnector == null) continue; if (thisConnector.IsValidObject == false) continue; // 현재 커넥터에 연결된 상대 커넥터를 찾는다. Connector otherConnector = FindConnectedTo(thisConnector); if (otherConnector != null) { if (otherConnector.IsValidObject == false) continue; Autodesk.Revit.DB.Mechanical.Duct otherDuct = doc.GetElement(otherConnector.Owner.Id) as Autodesk.Revit.DB.Mechanical.Duct; if (otherDuct == null) // 가지덕트 { continue; } // 현재 커넥터가 끝점에 있는 경우 if (cur_duct_ep.DistanceTo(ptThisConnector) < 0.0328084 ) // 1cm 미만 { totFlow = GetTotalFlow(otherDuct); SetAirFlowTr(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(curDuct.Id); continue; } // 현재 커넥터가 양 끝점 사이에 있는 경우 else if(cur_duct_sp.DistanceTo(ptThisConnector) > 0.0164042 && cur_duct_ep.DistanceTo(ptThisConnector) > 0.0164042) // 5mm { double curDuctFlow = GetTotalFlow(curDuct); totFlow = curDuctFlow; var lstCon = FindBranchConnectors(curDuct, ptThisConnector); // 현재 연결점에서 가지 덕트의 모든연결점을 찾는다. double maxW2 = 0d; foreach (Connector c in lstCon) { sortedConnectors.Remove(c); XYZ fPt = sortedConnectorPoints.Find(x => x.IsAlmostEqualTo(ptThisConnector)); if (fPt != null) { sortedConnectorPoints.Remove(fPt); } otherDuct = doc.GetElement(c.Owner.Id) as Autodesk.Revit.DB.Mechanical.Duct; if (otherDuct.Width > maxW2) maxW2 = otherDuct.Width; if (otherDuct == null) continue; double dblFlow1 = GetTotalFlow(otherDuct); if (Util.fuzzyEqual(dblFlow1, 0) == false) { totFlow += dblFlow1; } } if (curDuctFlow < 0.1) { SetAirFlowTr(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(curDuct.Id); continue; } //double cmh = totFlow * 101.9406477312; //frmDuctSize.Cal(cmh); //// 덕트 사이즈 반영 //double w1 = frmDuctSize.Width; //double w2 = Unit.FeetToMM(curDuct.Width); //double l_rd = 181 * Math.Abs(w2 - w1) / 2 / 75; //double ft_l_rd = Unit.MMToFeet(l_rd); XYZ v1 = (cur_duct_ep - thisConnector.Origin).Normalize(); XYZ ptBreak = thisConnector.Origin + v1 * maxW2* 1.5; //ptBreak = ptBreak + v1 * ft_l_rd; //Util.Pyosi(doc, ptBreak, true, clr_g); //MessageBox.Show("mp"); // thisConnector 가 현재 덕트의 양 끝점 사이에 존재하면 using (Transaction trans = new Transaction(doc)) { trans.Start("Break Duct"); curDuctLine = (curDuct.Location as LocationCurve).Curve as Line; ptBreak =curDuctLine.Project(ptBreak).XYZPoint; // ptBreak // ●---------------------x-----------------------------▶ // new curDuct double curFlow = GetTotalFlow(curDuct); ElementId idNew=MechanicalUtils.BreakCurve(doc, curDuct.Id, ptBreak); doc.Regenerate(); nBreak += 1; if (idNew != null) { newDuct = doc.GetElement(idNew) as Duct; if (newDuct != null) { //CopyAirFlowSize(newDuct, curDuct); //SetAirFlow(frmDuctSize, newDuct, totFlow); Line newLine = (newDuct.Location as LocationCurve).Curve as Line; Line curLine = (curDuct.Location as LocationCurve).Curve as Line; XYZ p1 = newLine.GetEndPoint(0); XYZ p2 = newLine.GetEndPoint(1); XYZ mp1 = Util.Midpoint(p1, p2); p1 = curLine.GetEndPoint(0); p2 = curLine.GetEndPoint(1); XYZ mp2 = Util.Midpoint(p1, p2); double d1 = cur_duct_sp.DistanceTo(mp1); double d2 = cur_duct_sp.DistanceTo(mp2); // 메인덕트에 가까운 쪽이 curDuct, 먼 쪽이 newDuct가 되도록 조정 if (d1 < d2) { Util.Swap(ref newDuct, ref curDuct); } SetAirFlow(frmDuctSize, newDuct, curFlow); SetAirFlow(frmDuctSize, curDuct, totFlow); idsAppliedFlow.Add(newDuct.Id); idsAppliedFlow.Add(curDuct.Id); // 절단점 연결 재설정 Connector conCurDuct = FindConnector(curDuct, ptBreak); Connector conNewDuct = FindConnector(newDuct, ptBreak); if (nBreak == 1) { //RemoveConnector(con_cur_duct_epOther, cur_duct_ep); //con_cur_duct_epOther.ConnectTo(con_cur_duct_ep); } //conNewDuct.ConnectTo(conCurDuct); var fi = doc.Create.NewTransitionFitting(conNewDuct, conCurDuct); } } trans.Commit(); } totFlow = 0; } } }//end-foreach } tGroup.Commit(); } } catch (Exception ex) { MessageBox.Show(ex.Message); } return Result.Succeeded; } /// /// 주어진 덕트로부터 풍량을 가져온다. /// /// /// private double GetTotalFlow(Duct duct) { double flow = 0d; Autodesk.Revit.DB.Parameter paramIF1 = duct.LookupParameter("TotalFlow"); if (paramIF1 != null && paramIF1.HasValue && paramIF1.StorageType == StorageType.Double) { flow = paramIF1.AsDouble(); } return flow; } /// /// 주어진 덕트로부터 개별 풍량을 가져온다. /// /// /// private double GetIndividualFlow(Duct duct) { double flow = 0d; Autodesk.Revit.DB.Parameter paramIF0 = duct.LookupParameter("IndividualFlow"); if (paramIF0 != null && paramIF0.HasValue && paramIF0.StorageType == StorageType.Double) { flow = paramIF0.AsDouble(); } return flow; } private void SetAirFlowTr(FormDuctSize frm, Duct curDuct, double totFlow) { Autodesk.Revit.DB.Parameter paramTotalFlow = curDuct.LookupParameter("TotalFlow"); using (Transaction trans = new Transaction(doc)) { trans.Start("Set Air Flow"); paramTotalFlow.Set(totFlow); // ft3/s if (totFlow > 0d) { // 덕트에 추가 풍량 반영 Autodesk.Revit.DB.Parameter paramAdditionFlow = curDuct.get_Parameter(BuiltInParameter.RBS_ADDITIONAL_FLOW); //Autodesk.Revit.DB.Parameter paramAdditionFlow = ductMain1.get_Parameter(BuiltInParameter.RBS_DUCT_FLOW_PARAM); if (paramAdditionFlow != null && paramAdditionFlow.StorageType == StorageType.Double) { if(paramAdditionFlow.IsReadOnly == false) paramAdditionFlow.Set(totFlow); } // 내부 흐름 기본 단위는 ft3/s; 1 ft3/s = 101.9406477312 m3/h, 1m3/h = 0.0098096296448581 // 1 m3/h = 0.009809629644857942 ft3/s double cmh = totFlow * 101.9406477312; frm.Cal(cmh); // 덕트 사이즈 반영 curDuct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(Unit.MMToFeet(frm.Width)); curDuct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(Unit.MMToFeet(frm.Height)); } trans.Commit(); } } private void SetAirFlow(FormDuctSize frm, Duct curDuct, double totFlow) { Autodesk.Revit.DB.Parameter paramTotalFlow = curDuct.LookupParameter("TotalFlow"); paramTotalFlow.Set(totFlow); // ft3/s if (totFlow > 0d) { // 덕트에 추가 풍량 반영 Autodesk.Revit.DB.Parameter paramAdditionFlow = curDuct.get_Parameter(BuiltInParameter.RBS_ADDITIONAL_FLOW); //Autodesk.Revit.DB.Parameter paramAdditionFlow = ductMain1.get_Parameter(BuiltInParameter.RBS_DUCT_FLOW_PARAM); if (paramAdditionFlow != null && paramAdditionFlow.StorageType == StorageType.Double) { if(paramAdditionFlow.IsReadOnly==false) paramAdditionFlow.Set(totFlow); } // 내부 흐름 기본 단위는 ft3/s; 1 ft3/s = 101.9406477312 m3/h, 1m3/h = 0.0098096296448581 // 1 m3/h = 0.009809629644857942 ft3/s double cmh = totFlow * 101.9406477312; frm.Cal(cmh); // 덕트 사이즈 반영 curDuct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(Unit.MMToFeet(frm.Width)); curDuct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(Unit.MMToFeet(frm.Height)); } } private void CopyAirFlowSize(Duct dstDuct, Duct srcDuct ) { double totFlow = GetTotalFlow(srcDuct); double indFlow = GetIndividualFlow(srcDuct); dstDuct.LookupParameter("TotalFlow").Set(totFlow); dstDuct.LookupParameter("IndividualFlow").Set(indFlow); // 덕트에 추가 풍량 반영 Autodesk.Revit.DB.Parameter paramAdditionFlow = dstDuct.get_Parameter(BuiltInParameter.RBS_ADDITIONAL_FLOW); //Autodesk.Revit.DB.Parameter paramAdditionFlow = ductMain1.get_Parameter(BuiltInParameter.RBS_DUCT_FLOW_PARAM); if (paramAdditionFlow != null && paramAdditionFlow.StorageType == StorageType.Double) { if(paramAdditionFlow.IsReadOnly==false) paramAdditionFlow.Set(totFlow); } dstDuct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(srcDuct.Width); dstDuct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(srcDuct.Height); } private void InitDuctFlow(Autodesk.Revit.DB.Mechanical.Duct ductMain, DefinitionFile informationFile, string parameterName) { Definition defIndividualFlow = null; Autodesk.Revit.DB.Parameter paramIF = ductMain.LookupParameter(parameterName); SharedParameterBindingManager manager = new SharedParameterBindingManager(); manager.parameterName = parameterName; //int nVersionNum = 2019; //int nVal =0 ; //if(int.TryParse(m_pUIApp.Application.VersionNumber, out nVal)) nVersionNum=nVal; #if _22 || _23 manager.parameterType = SpecTypeId.AirFlow; #else manager.parameterType = ParameterType.HVACAirflow; #endif manager.UserModifiable = true; if (paramIF == null) { DefinitionGroup defGroup = informationFile.Groups.get_Item("Duct"); if (defGroup != null) { defIndividualFlow = defGroup.Definitions.get_Item(parameterName); if (defIndividualFlow != null) { // Create a new Binding object with the categories to which the parameter will be bound. CategorySet categories = m_pUIApp.Application.Create.NewCategorySet(); // get door category and insert into the CategorySet. Category ductCategory = m_pUIApp.ActiveUIDocument.Document.Settings.Categories. get_Item(BuiltInCategory.OST_PlaceHolderDucts); categories.Insert(ductCategory); InstanceBinding instanceBinding = m_pUIApp.Application.Create.NewInstanceBinding(categories); BindingMap bindingMap = m_pUIApp.ActiveUIDocument.Document.ParameterBindings; // for "IndividualFlow" if (!AlreadyAddedSharedParameter(m_pUIApp.ActiveUIDocument.Document, parameterName, BuiltInCategory.OST_PlaceHolderDucts)) { Definition instanceIndividualFlow = defGroup.Definitions.get_Item(parameterName); if (null == instanceIndividualFlow) { #if _23 ExternalDefinitionCreationOptions ExternalDefinitionCreationOptions2 = new ExternalDefinitionCreationOptions(parameterName, SpecTypeId.AirFlow); #else ExternalDefinitionCreationOptions ExternalDefinitionCreationOptions2 = new ExternalDefinitionCreationOptions(parameterName, ParameterType.HVACAirflow); #endif instanceIndividualFlow = defGroup.Definitions.Create(ExternalDefinitionCreationOptions2); } using (Transaction trans = new Transaction(doc)) { trans.Start("Add Shared Parameter"); // Add the binding and definition to the document. bindingMap.Insert(instanceIndividualFlow, instanceBinding, BuiltInParameterGroup.PG_MECHANICAL_AIRFLOW); trans.Commit(); } } } } } } private DefinitionFile OpenSharedParameter() { //Method's return DefinitionFile informationFile = null; // create shared parameter file var location = Util.GetKMBIMLibraryFolder("SharedParameter"); string sharedParameterFile = Path.Combine(location, "KMBIMSharedParameter.txt"); if (File.Exists(sharedParameterFile)) { m_pUIApp.Application.SharedParametersFilename = sharedParameterFile; informationFile = m_pUIApp.Application.OpenSharedParameterFile(); } return informationFile; } /// /// Has the specific document shared parameter already been added ago? /// /// Revit project in which the shared parameter will be added. /// the name of the shared parameter. /// Which category the parameter will bind to /// Returns true if already added ago else returns false. private bool AlreadyAddedSharedParameter(Document doc, string paraName, BuiltInCategory boundCategory) { try { BindingMap bindingMap = doc.ParameterBindings; DefinitionBindingMapIterator bindingMapIter = bindingMap.ForwardIterator(); while (bindingMapIter.MoveNext()) { if (bindingMapIter.Key.Name.Equals(paraName)) { ElementBinding binding = bindingMapIter.Current as ElementBinding; CategorySet categories = binding.Categories; foreach (Category category in categories) { if (category.Id.IntegerValue.Equals((int)boundCategory)) { return true; } } } } } catch (Exception) { return false; } return false; } private bool RemoveConnector(Connector conThis, Autodesk.Revit.DB.XYZ pt) { bool bRC = false; if (conThis == null) return bRC; ConnectorSet connSet = conThis.AllRefs; foreach (Connector con in connSet) { if (conThis.Origin.IsAlmostEqualTo(pt)) { con.DisconnectFrom(conThis); bRC = true; } } return bRC; } private Connector FindConnector(Autodesk.Revit.DB.Mechanical.Duct duct, Autodesk.Revit.DB.XYZ conXYZ) { ConnectorSet conns = duct.ConnectorManager.Connectors; foreach (Connector conn in conns) { if (conn.Origin.IsAlmostEqualTo(conXYZ)) { return conn; } } return null; } private List FindBranchConnectors(Autodesk.Revit.DB.Mechanical.Duct duct, Autodesk.Revit.DB.XYZ conXYZ) { List connectors = new List(); ConnectorSet conns = duct.ConnectorManager.Connectors; if (conns.Size < 2) return connectors; Line ductLine = (duct.Location as LocationCurve).Curve as Line; foreach (Connector conn in conns) { if (conn.Origin.IsAlmostEqualTo(conXYZ)) { Connector conOther=FindConnectedTo(conn); if (conOther != null) { Duct ductOther = conOther.Owner as Duct; Line ductOtherLine = (ductOther.Location as LocationCurve).Curve as Line; if(Util.IsParallel(ductLine.Direction, ductOtherLine.Direction) == false) { connectors.Add(conOther); } } } } return connectors; } private Connector FindConnectedTo(Autodesk.Revit.DB.Mechanical.Duct duct, Autodesk.Revit.DB.XYZ conXYZ) { Connector connItself = FindConnector(duct, conXYZ); ConnectorSet connSet = connItself.AllRefs; foreach (Connector conn in connSet) { if (conn.Owner.Id.IntegerValue != duct.Id.IntegerValue && conn.ConnectorType == ConnectorType.End) { return conn; } } return null; } private Connector FindConnectedTo(Connector connItself) { if (connItself == null) return null; ConnectorSet connSet = connItself.AllRefs; foreach (Connector conn in connSet) { if (conn.Owner.Id.IntegerValue != connItself.Owner.Id.IntegerValue && conn.ConnectorType == ConnectorType.End && connItself.Origin.IsAlmostEqualTo(conn.Origin)) { return conn; } } return null; } private ElementId GetViewLevel(Document doc) { Autodesk.Revit.DB.View active = doc.ActiveView; ElementId levelId = null; Autodesk.Revit.DB.Parameter level = active.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 == level.AsString()) { levelId = lvl.Id; break; } } return levelId; } public XYZ getXYZ(UIDocument uidoc, System.Drawing.Point p) { UIView uiview = GetActiveUiView(uidoc); Autodesk.Revit.DB.Rectangle rect = uiview.GetWindowRectangle(); System.Windows.Forms.Cursor.Position = new System.Drawing.Point(p.X, p.Y); double dx = (double)(p.X - rect.Left) / (rect.Right - rect.Left); double dy = (double)(p.Y - rect.Bottom) / (rect.Top - rect.Bottom); IList corners = uiview.GetZoomCorners(); XYZ a = corners[0]; XYZ b = corners[1]; XYZ v = b - a; XYZ p3 = a + dx * v.X * XYZ.BasisX + dy * v.Y * XYZ.BasisY; return p3; } public System.Drawing.Point getScreenPoint() { return System.Windows.Forms.Cursor.Position; } private UIView GetActiveUiView(UIDocument uidoc) { Document doc = uidoc.Document; Autodesk.Revit.DB.View view = doc.ActiveView; IList uiviews = uidoc.GetOpenUIViews(); UIView uiview = null; foreach (UIView uv in uiviews) { if (uv.ViewId.Equals(view.Id)) { uiview = uv; break; } } return uiview; } } }