Client/Desktop/KMBIM3.0/23.10.16/Cmd/Duct/DuctSize/DuctSizeCmd.cs

1096 lines
46 KiB
C#

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
{
/// <summary>
/// Implements interface IExternalCommand of Revit API.
/// </summary>
[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<ElementId> _added_emement_ids = new List<ElementId>();
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<DuctType> ductCollection = new FilteredElementCollector(doc)
.OfClass(typeof(DuctType))
.OfType<DuctType>()
.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<Duct> lstDuctPlaceholder = new List<Duct>();
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<DuctType> ductCollection = new FilteredElementCollector(doc)
.OfClass(typeof(DuctType))
.OfType<DuctType>()
.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<FamilySymbol>().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<ElementId> selIds = new List<ElementId>(); // 선택된 아이디
List<ElementId> visitedIds = new List<ElementId>(); // 방문한 덕트 아이디
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<ElementId> idsAppliedFlow = new List<ElementId>(); // 방문한 덕트 아이디
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<Connector> sourceConnectors = new List<Connector>();
List<Connector> sortedConnectors = new List<Connector>();
foreach (Connector c in conManCurDuct.Connectors)
{
// 시작 연결점은 제외
if (c.IsConnected && cur_duct_sp.IsAlmostEqualTo(c.Origin) == false)
sourceConnectors.Add(c);
}
List<XYZ> sortedConnectorPoints = new List<XYZ>();
// 정렬
// 덕트말단 또는 이미 풍량을 반영한 덕트(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;
}
/// <summary>
/// 주어진 덕트로부터 풍량을 가져온다.
/// </summary>
/// <param name="duct"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 주어진 덕트로부터 개별 풍량을 가져온다.
/// </summary>
/// <param name="duct"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Has the specific document shared parameter already been added ago?
/// </summary>
/// <param name="doc">Revit project in which the shared parameter will be added.</param>
/// <param name="paraName">the name of the shared parameter.</param>
/// <param name="boundCategory">Which category the parameter will bind to</param>
/// <returns>Returns true if already added ago else returns false.</returns>
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<Connector> FindBranchConnectors(Autodesk.Revit.DB.Mechanical.Duct duct, Autodesk.Revit.DB.XYZ conXYZ)
{
List<Connector> connectors = new List<Connector>();
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<Element> 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<XYZ> 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<UIView> uiviews = uidoc.GetOpenUIViews();
UIView uiview = null;
foreach (UIView uv in uiviews)
{
if (uv.ViewId.Equals(view.Id))
{
uiview = uv;
break;
}
}
return uiview;
}
}
}