Client/Desktop/KMBIM3.0/KMBIM3.0_23.08.16_수정최종/Cmd/Duct/DuctDraw/DuctDrawCmd.cs

473 lines
18 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.DuctDraw
{
/// <summary>
/// 덕트 대행자(PlaceHolder:자리 표시자)를 덕트로 변환합니다. 꼬메의 자동작도와 유사한 기능
/// </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 DuctDrawCmd : IExternalCommand
{
UIApplication m_pUIApp;
UIDocument uidoc = null;
Document doc = null;
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;
// 선택한 요소 가져오기
var ductref = uidoc.Selection.PickObject(ObjectType.Element, "메인 덕트 대행자 선택");
if (ductref == null) return Result.Failed;
Autodesk.Revit.DB.Mechanical.Duct curSelDuct = doc.GetElement(ductref.ElementId) as Duct;
if (curSelDuct == null) return Result.Failed;
// 선택한 덕트 대행자와 연결된 모든 덕트 대행자 찾기
var connectedDucts = new List<ElementId>();
var selectedDucts = new List<ElementId>();
selectedDucts.Add(curSelDuct.Id);
ElementId curId;
while (selectedDucts.Count > 0)
{
curId = selectedDucts.First();
selectedDucts.RemoveAt(0);
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;
if(duct.IsPlaceholder) connectedDucts.Add(curId);
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 (connectedDucts.Contains(otherConnector.Owner.Id) == false) // 방문 이력이 없는 덕트 아이디만 추가
{
selectedDucts.Add(otherConnector.Owner.Id);
}
}
}
}
}
// Duct 타입 가져오기
DuctType ductType = new FilteredElementCollector(doc)
.OfClass(typeof(DuctType))
.Cast<DuctType>()
.FirstOrDefault(x => x.Name == "Rectangular");
// 현재 선택한 덕트가 대행자인 경우에만 처리
if (curSelDuct.IsPlaceholder)
{
// 대행자를 Duct로 변환
using (Transaction tx = new Transaction(doc))
{
tx.Start("Convert Placeholder to Duct");
Autodesk.Revit.DB.Mechanical.MechanicalUtils.ConvertDuctPlaceholders(doc, connectedDucts);
tx.Commit();
}
}
/*
MechanicalSystemType ductSystemType = null;
Selection sel1 = uidoc.Selection;
DefinitionFile informationFile = OpenSharedParameter();
if (null == informationFile)
{
return Result.Failed;
}
XYZ m_pt1 = sel1.PickPoint("시작점 지정");
Duct m_duct = null;
Level viewLevel = Util.GetLevel(doc, doc.ActiveView.Origin.Z, 50.0);
ElementId levelId = viewLevel != null ? viewLevel.Id : null;
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);
XYZ m_pt2 = sel1.PickPoint("다음점 지정");
using (Transaction t = new Transaction(doc))
{
t.Start("덕트 대행자 생성");
XYZ vDir = (m_pt2 - m_pt1);
XYZ vNDir = (m_pt2 - m_pt1).Normalize();
XYZ m_ptMid = m_pt1 + vNDir * vDir.GetLength() * 0.5;
Duct duct1 = Duct.CreatePlaceholder(doc, ductSystemType.Id, ductType.Id, levelId, m_pt1, m_ptMid);
// 덕트 사이즈 반영
duct1.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(Unit.MMToFeet(500));
duct1.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(Unit.MMToFeet(300));
// 교차 확인 요소
KDCSIntersectorElement intersectorElement1 = new KDCSIntersectorElement(duct1);
Duct duct2 = Duct.CreatePlaceholder(doc, ductSystemType.Id, ductType.Id, levelId, m_ptMid, m_pt2);
KDCSIntersectorElement intersectorElement2 = new KDCSIntersectorElement(duct2);
// 덕트 사이즈 반영
duct2.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(Unit.MMToFeet(300));
duct2.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(Unit.MMToFeet(250));
Connector con1 = intersectorElement1.GetClosestConnector(m_ptMid);
Connector con2 = intersectorElement2.GetClosestConnector(m_ptMid);
con1.ConnectTo(con2);
var fi = doc.Create.NewTransitionFitting(con1, con2);
t.Commit();
}
*/
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return Result.Failed;
}
return Result.Succeeded;
}
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;
#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 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 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)
{
ConnectorSet connSet = connItself.AllRefs;
foreach (Connector conn in connSet)
{
if (conn.Owner.Id.IntegerValue != connItself.Owner.Id.IntegerValue &&
conn.ConnectorType == ConnectorType.End)
{
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);
if (uiview == null) return null;
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;
}
}
}