Client/Desktop/KMBIM3.0/KMBIM3.0_소스/Cmd/PartSpacing/PartSpacing - 수정 전.cs

617 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using System.Windows.Forms;
using Autodesk.Revit.DB.Mechanical;
using KDCS.Utils;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class PartSpacing : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
Autodesk.Revit.DB.View view;
ExternalCommandData m_commandData;
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
uiapp = commandData.Application;
uidoc = uiapp.ActiveUIDocument;
doc = uidoc.Document;
m_commandData = commandData;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
view = doc.ActiveView;
bool b_Cap = false, b_Reducer = false;
double m_Dist = 0;
List<Element> m_SelElemLst = new List<Element>();
List<FamilyInstance> m_SelTeeLst = new List<FamilyInstance>();
List<FamilyInstance> m_SelRDCLst = new List<FamilyInstance>();
List<FamilyInstance> m_SelCapLst = new List<FamilyInstance>();
try
{
MainForm dlg = new MainForm();
dlg.Dist = 100;
dlg.Cap = true;
dlg.Reducer = true;
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.Cancel) return Result.Succeeded;
b_Cap = dlg.Cap;
b_Reducer = dlg.Reducer;
m_Dist = dlg.Dist;
IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element);
//선택한 객체들 Element로 리스트에 저장
if (pickrefs != null)
{
foreach (Reference refer in pickrefs)
{
ElementId elemID = refer.ElementId;
Element selElem = doc.GetElement(elemID);
m_SelElemLst.Add(selElem);
}
}
else
return Result.Succeeded;
////선택된 객체중 패밀리 TEE를 리스트에 모음.
//foreach (Element e in m_SelElemLst)
//{
// if (e is FamilyInstance)
// {
// FamilyInstance family = e as FamilyInstance;
// var param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
// if ((PartType)param.AsInteger() == PartType.Tee)
// m_SelTeeLst.Add(family);
//
// }
//}
//Reference reference = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
//Element selElem2 = doc.GetElement(reference);
//List<Element> m_sideElement = new List<Element>();
//
//foreach (Element Tee in m_SelTeeLst)
//{
// GetSideElement(Tee, ref m_sideElement);
//}
//foreach (FamilyInstance family in m_SelTeeLst)
//{
// ConnectorSet conSet = family.MEPModel.ConnectorManager.Connectors;
// foreach (Connector con in conSet)
// {
// Pyosi(con.Origin, 1);
// MessageBox.Show("1");
// break;
// }
//}
//선택된 객체중 패밀리 레듀셔,캡을 리스트에 모음.
foreach (Element e in m_SelElemLst)
{
if (e is FamilyInstance)
{
FamilyInstance family = e as FamilyInstance;
var param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
if ((PartType)param.AsInteger() == PartType.Transition)
m_SelRDCLst.Add(family);
else if ((PartType)param.AsInteger() == PartType.Cap)
m_SelCapLst.Add(family);
}
}
if (b_Reducer)
{
foreach (Element Reducer in m_SelRDCLst)
{
Set_Reducer_Distance(Reducer, m_Dist);
}
}
if (b_Cap)
{
foreach (Element Cap in m_SelCapLst)
{
Set_Cap_Distance(Cap, m_Dist);
}
}
}
catch (Exception e)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
public void Set_Cap_Distance(Element Elem, double Dist)
{
if (Elem is FamilyInstance)
{
ConnectorSet FamilyConSet = (Elem as FamilyInstance).MEPModel.ConnectorManager.Connectors;
Connector BaseCon = null;
//캡은 커넥터가 하나이기 때문에 바로 BaseCon으로 지정.
foreach (Connector con in FamilyConSet)
{
BaseCon = con;
}
//캡 커넥터에 붙은 객체 커넥터
Connector NextCon = GetNextElementConnector(BaseCon);
if (NextCon.Owner is FamilyInstance)
{
}
else if (NextCon.Owner is Pipe)
{
//파이프 반대쪽 커넥터
Connector NextOtherCon = GetOtherConnector(NextCon);
//캡에 붙은 파이프 커넥터 ->파이프 반대 커넥터 방향
XYZ DirecPt = (NextOtherCon.Origin - NextCon.Origin).Normalize();
XYZ sp_pipe = null, ep_pipe = null;
Util.GetStartEndPoint(NextCon.Owner as Pipe, ref sp_pipe, ref ep_pipe);
double PipeDist = sp_pipe.DistanceTo(ep_pipe);
MoveElement(doc, BaseCon.Owner as FamilyInstance, NextCon.Origin, DirecPt, Unit.FeetToMM(PipeDist) - Dist);
}
}
}
// Reducer 간격 맞추기.
public void Set_Reducer_Distance(Element Elem, double Dist)
{
if (Elem is FamilyInstance)
{
ConnectorSet FamilyConSet = (Elem as FamilyInstance).MEPModel.ConnectorManager.Connectors;
List<Connector> m_ElemConLst = Util.GetElementConnectors(Elem);
//레듀셔의 큰쪽을 Base로 작업
//레듀셔 큰->작은 방향
Connector BaseCon = null;
Connector OtherCon = null;
XYZ DirecPt = null;
if (m_ElemConLst.Count == 2)
{
if (m_ElemConLst[0].Radius > m_ElemConLst[1].Radius)
{
BaseCon = m_ElemConLst[0];
DirecPt = (m_ElemConLst[1].Origin - m_ElemConLst[0].Origin).Normalize();
OtherCon = m_ElemConLst[1];
}
else
{
BaseCon = m_ElemConLst[1];
DirecPt = (m_ElemConLst[0].Origin - m_ElemConLst[1].Origin).Normalize();
OtherCon = m_ElemConLst[0];
}
}
//T와 레듀셔 사이에 기존 파이프 타입을 가져오기위해 주변에서 파이프 찾기.
Connector OtherNextCon = GetNextElementConnector(OtherCon);
Pipe pipe = null;
if (OtherNextCon.Owner is Pipe)
{
pipe = OtherNextCon.Owner as Pipe;
}
if (BaseCon.IsConnected == true)
{
//레듀셔 커넥터에 연결된 다음 객체 커넥터 구하기
Connector NextCon = GetNextElementConnector(BaseCon);
if (NextCon.Owner is FamilyInstance)//레듀셔 옆이 패밀리인가
{
if (GetFamilyPartType(NextCon, PartType.Elbow) || GetFamilyPartType(NextCon, PartType.Tee))
{
//레듀셔와 엘보 또는 티 커넥터 끊기
using (Transaction trans = new Transaction(doc))
{
trans.Start("DisConnect");
BaseCon.DisconnectFrom(NextCon);
MoveElement(doc, BaseCon.Owner as FamilyInstance, BaseCon.Origin, DirecPt, Dist);
Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).First() as Level;
Pipe newPipe = Pipe.Create(doc, pipe.GetTypeId(), pipe.LevelId, BaseCon, NextCon);
trans.Commit();
}
}
//레듀셔 작은쪽에 붙은 객체 커넥터
Connector RedNextOtherCon = GetNextElementConnector(OtherCon);
if (GetFamilyPartType(NextCon, PartType.Elbow) || GetFamilyPartType(NextCon, PartType.Tee))
{
//레듀셔와 엘보 또는 티 커넥터 끊기
using (Transaction trans = new Transaction(doc))
{
trans.Start("DisConnect");
OtherCon.DisconnectFrom(RedNextOtherCon);
MoveElement(doc, OtherCon.Owner as FamilyInstance, OtherCon.Origin, DirecPt, Dist);
Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).First() as Level;
Pipe newPipe = Pipe.Create(doc, pipe.GetTypeId(), pipe.LevelId, OtherCon, RedNextOtherCon);
trans.Commit();
}
}
}
else if (NextCon.Owner is Pipe)//레듀셔 옆이 파이프인가
{
Connector NextOtherCon = GetOtherConnector(NextCon);
Connector NextCon2 = GetNextElementConnector(NextOtherCon);
if (NextCon2.Owner is FamilyInstance)
{
if (GetFamilyPartType(NextCon2, PartType.Elbow) || GetFamilyPartType(NextCon2, PartType.Tee))
{
XYZ sp_pipe = null, ep_pipe = null;
Util.GetStartEndPoint(NextCon.Owner as Pipe, ref sp_pipe, ref ep_pipe);
double PipeDist = sp_pipe.DistanceTo(ep_pipe);
MoveElement(doc, BaseCon.Owner as FamilyInstance, NextCon.Origin, DirecPt, Dist - Unit.FeetToMM(PipeDist));
}
}
}
}
}
}
//Element 커넥터에 붙어있는 객체를 구하는 함수
public void GetSideElement(Element Elem, ref List<Element> m_SideElements)
{
ConnectorSet ElemConSet = null;
if (Elem is FamilyInstance)
ElemConSet = (Elem as FamilyInstance).MEPModel.ConnectorManager.Connectors;
else if (Elem is Pipe)
ElemConSet = (Elem as Pipe).ConnectorManager.Connectors;
else if (Elem is Duct)
ElemConSet = (Elem as Duct).ConnectorManager.Connectors;
foreach (Connector ElemCon in ElemConSet)//Tee 커넥터
{
if (ElemCon.MEPSystem != null)
{
if (ElemCon.IsConnected == true)
{
//현재 커넥터에 연결된 다음 객체의 커넥터 구하기
Connector NextCon = GetNextElementConnector(ElemCon);
if (NextCon == null) continue;
if (NextCon.Owner is FamilyInstance)
{
bool tf = GetFamilyPartType(NextCon, PartType.Transition);
if (tf)//레듀셔일 때
{
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("1");
//현재 커넥터의 객체가 커넥터가 2개일 때 현재 커넥터의 반대쪽 커넥터 구하기.
Connector NextOtherCon1 = GetOtherConnector(NextCon);
if (NextCon.Radius < NextOtherCon1.Radius) continue;
FamilyInstance m_Reducer = NextCon.Owner as FamilyInstance;
//레듀셔 옆 파이프 또는 덕트 커넥터 구하기
Connector NextOtherCon2 = GetNextElementConnector(NextOtherCon1);
if (NextOtherCon2 == null) continue;
//Tee와 레듀셔의 교차 커넥터 끊기
using (Transaction trans = new Transaction(doc))
{
trans.Start("DisConnect");
ElemCon.DisconnectFrom(NextCon);
trans.Commit();
}
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("1");
//Pyosi(NextOtherCon1.Origin, 1);
//MessageBox.Show("2");
//Tee에 연결된 레듀셔의 커넥터에서 - 레듀셔 방향
XYZ VecPt = (NextOtherCon1.Origin - NextCon.Origin).Normalize();
//레듀셔 위치 조정
MoveElement(doc, NextCon.Owner as FamilyInstance, NextCon.Origin, VecPt, 200);
if (NextOtherCon2.Owner is Pipe)
{
Pipe pipe = NextOtherCon2.Owner as Pipe;
using (Transaction trans = new Transaction(doc))
{
trans.Start("CreatePipe");
Level level = new FilteredElementCollector(doc).OfClass(typeof(Level)).First() as Level;
Pipe newPipe = Pipe.Create(doc, pipe.GetTypeId(), pipe.LevelId, ElemCon, NextCon);
trans.Commit();
}
}
}
else
{
}
}
else if (NextCon.Owner is Pipe || NextCon.Owner is Duct)
{
//현재 커넥터의 객체가 커넥터가 2개일 때 현재 커넥터의 반대쪽 커넥터 구하기.
Connector NextOtherCon1 = GetOtherConnector(NextCon);
Pipe pipe = null;
Duct duct = null;
if (NextCon.Owner is Pipe)
{
//Pyosi(NextCon.Origin, 1);
//MessageBox.Show("NextCon");
pipe = NextCon.Owner as Pipe;
//파이프 옆 패밀리 커넥터 구하기
Connector familyCon = GetNextElementConnector(NextOtherCon1);
if (familyCon == null) continue;
//Pyosi(familyCon.Origin, 1);
//MessageBox.Show("familyCon");
bool tf = GetFamilyPartType(familyCon, PartType.Transition);
if (tf)
{
//현재 커넥터의 객체가 커넥터가 2개일 때 현재 커넥터의 반대쪽 커넥터 구하기.
Connector familyOtherCon = GetOtherConnector(familyCon);
if (familyCon.Radius < familyOtherCon.Radius) continue;
//Pyosi(familyOtherCon.Origin, 1);
//MessageBox.Show("familyOtherCon");
FamilyInstance m_Reducer = familyOtherCon.Owner as FamilyInstance;
Connector NextOtherCon2 = GetNextElementConnector(familyOtherCon);
if (NextOtherCon2 == null) continue;
//Pyosi(NextOtherCon2.Origin, 1);
//MessageBox.Show("NextOtherCon2");
XYZ VecPt = (NextCon.Origin - NextOtherCon1.Origin).Normalize();
double PipeDist = NextOtherCon1.Origin.DistanceTo(NextCon.Origin);
//레듀셔 위치 조정
MoveElement(doc, familyCon.Owner as FamilyInstance, NextCon.Origin, VecPt, Unit.FeetToMM(PipeDist) - 200);
if (NextOtherCon2.Owner is Pipe)
{
Pipe pipe2 = NextOtherCon2.Owner as Pipe;
//NextOtherCon2.Origin
}
}
}
else if (NextCon.Owner is Duct)
{
duct = NextCon.Owner as Duct;
//덕트 옆 패밀리 커넥터 구하기
Connector NextOtherCon2 = GetNextElementConnector(NextOtherCon1);
}
}
//Pyosi(aa.Origin,1);
//MessageBox.Show("1");
}
}
}
}
//객체 이동 함수
public void MoveElement(Autodesk.Revit.DB.Document doc, FamilyInstance family, XYZ BasePt, XYZ VecPt, double mm_MoveDist)
{
LocationPoint familyLoc = family.Location as LocationPoint;
//polar점 구하기.
XYZ plrPt = Util.Polar(BasePt, VecPt, Unit.MMToFeet(mm_MoveDist));
//커넥터 점과 Polar로 구한점을 빼 이동할 거리 만들기.
XYZ NewPt = new XYZ(plrPt.X - BasePt.X, plrPt.Y - BasePt.Y, plrPt.Z - BasePt.Z);
//Pyosi(NewPt, 1);
//MessageBox.Show("1");
ElementTransformUtils.MoveElement(doc, family.Id, NewPt);
familyLoc = family.Location as LocationPoint;
XYZ newActual = familyLoc.Point;
}
//패밀리의 타입구분
public bool GetFamilyPartType(Connector baseCon, PartType partType)
{
if (baseCon.Owner is FamilyInstance)
{
FamilyInstance family = baseCon.Owner as FamilyInstance;
Parameter param = family.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
if (partType == (PartType)param.AsInteger())
return true;
else
return false;
}
return false;
}
//객체의 다른 커넥터 구하기.(객체의 커넥터가 2개일 때.)
public Connector GetOtherConnector(Connector baseCon)
{
Connector resCon = null;
ConnectorSet ConSet = null;
MEPSystem mepSystem = baseCon.MEPSystem;
FamilyInstance family = null;
Pipe pipe = null;
Duct duct = null;
if (mepSystem != null)
{
if (baseCon.IsConnected == true)
{
if (baseCon.Owner is FamilyInstance)
{
family = baseCon.Owner as FamilyInstance;
ConSet = family.MEPModel.ConnectorManager.Connectors;
}
else if (baseCon.Owner is Pipe)
{
pipe = baseCon.Owner as Pipe;
ConSet = pipe.ConnectorManager.Connectors;
}
else if (baseCon.Owner is Duct)
{
duct = baseCon.Owner as Duct;
ConSet = duct.ConnectorManager.Connectors;
}
foreach (Connector con in ConSet)
{
//입력 커넥터와 같은 커넥터는 넘긴다,
if (con.Origin.IsAlmostEqualTo(baseCon.Origin, Unit.MMToFeet(0.001)))
{
//Pyosi(con.Origin, 1);
//MessageBox.Show("1");
continue;
}
else
{
//Pyosi(con.Origin, 1);
//MessageBox.Show("2");
resCon = con;
}
}
}
}
//Pyosi(resCon.Origin, 1);
//MessageBox.Show("2");
return resCon;
}
//커넥터에 연결된 다음 객체의 커넥터 구하기.
public Connector GetNextElementConnector(Connector baseCon)
{
Connector resCon = null;
MEPSystem mepSystem = baseCon.MEPSystem;
if (mepSystem != null)
{
if (baseCon.IsConnected == true)
{
ConnectorSet ConSet = baseCon.AllRefs;
ConnectorSetIterator csi = ConSet.ForwardIterator();
while (csi.MoveNext())
{
Connector connected = csi.Current as Connector;
if (connected != null && connected.ConnectorType == ConnectorType.End)
{
if (baseCon.Origin.IsAlmostEqualTo(connected.Origin, Unit.MMToFeet(0.001)))
{
if (connected.IsConnected == true)
{
ConnectorSet ConnectedSet = null;
FamilyInstance family = null;
Pipe pipe = null;
Duct duct = null;
if (connected.Owner is FamilyInstance)
{
family = connected.Owner as FamilyInstance;
ConnectedSet = family.MEPModel.ConnectorManager.Connectors;
}
else if (connected.Owner is Pipe)
{
pipe = connected.Owner as Pipe;
ConnectedSet = pipe.ConnectorManager.Connectors;
}
else if (connected.Owner is Duct)
{
duct = connected.Owner as Duct;
ConnectedSet = duct.ConnectorManager.Connectors;
}
foreach (Connector NextCon in ConnectedSet)
{
if (connected.Origin.IsAlmostEqualTo(NextCon.Origin, Unit.MMToFeet(0.001)))
{
resCon = NextCon;
}
}
}
}
}
}//while end
}
}
//Pyosi(resCon.Origin, 1);
//MessageBox.Show("1");
return resCon;
}
public bool Pyosi(XYZ pt, int TranMode)
{
if (TranMode == 0)
{
XYZ pt1 = new XYZ(pt.X - 0.328084, pt.Y + 0.328084, pt.Z);
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS), pt.Z);
XYZ pt3 = new XYZ(pt.X + 0.328084, pt.Y - 0.328084, pt.Z);
XYZ pt4 = new XYZ(pt.X - 0.328084, pt.Y - 0.328084, pt.Z);
Autodesk.Revit.DB.View view = doc.ActiveView;
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
}
else
{
using (Transaction transaction = new Transaction(doc))
{
transaction.Start("Start");
XYZ pt1 = new XYZ(pt.X - 0.328084, pt.Y + 0.328084, pt.Z);
XYZ pt2 = new XYZ(pt.X + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS), pt.Y + Unit.CovertToAPI(100, DisplayUnitType.DUT_MILLIMETERS), pt.Z);
XYZ pt3 = new XYZ(pt.X + 0.328084, pt.Y - 0.328084, pt.Z);
XYZ pt4 = new XYZ(pt.X - 0.328084, pt.Y - 0.328084, pt.Z);
Autodesk.Revit.DB.View view = doc.ActiveView;
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt1, pt3);
Util.NewModelLine(uiapp, view.SketchPlane.GetPlane(), pt2, pt4);
transaction.Commit();
}
}
return true;
}
}
}