1096 lines
46 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
} |