Client/Desktop/KMBIM3.0/23.10.18/Cmd/TrimSpacing/DuctTrimSpacing.cs

383 lines
18 KiB
C#

using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using Autodesk.Revit.UI.Selection;
using KDCS.Utils;
using Autodesk.Revit.DB.Structure;
using KMBIM.Revit.Tools.Cmd.SprinklerConnect;
using Autodesk.Revit.DB.Mechanical;
using KMBIM.Revit.Tools;
namespace KMBIM
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class DuctTrimSpacing : IExternalCommand
{
UIApplication uiapp;
UIDocument uidoc;
Autodesk.Revit.DB.Document doc;
Autodesk.Revit.Creation.Application creApp;
Autodesk.Revit.Creation.Document creDoc;
Autodesk.Revit.UI.ExternalCommandData m_commandData;
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
m_commandData = commandData;
uiapp = commandData.Application;
uidoc = uiapp.ActiveUIDocument;
doc = uidoc.Document;
creApp = uiapp.Application.Create;
creDoc = doc.Create;
double m_TrimDist = 0;
List<Element> m_ElemLst = new List<Element>();
try
{
Form_TrimSpacing dlg = new Form_TrimSpacing();
//라벨 mm / 길이 : 1740 변경
dlg.m_label = "mm";
dlg.m_trimDist = 1740;
dlg.ShowDialog();
if (dlg.DialogResult == DialogResult.Cancel) return Result.Cancelled;
//대화상자 값 가져오기
m_TrimDist = Math.Round(dlg.m_trimDist);
//IList<Reference> pickrefs = commandData.Application.ActiveUIDocument.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "절단할 덕트 선택 : ");
//if (pickrefs == null) return Result.Cancelled;
//foreach (Reference refer in pickrefs)
//{
// ElementId id = refer.ElementId;
// Element elem = doc.GetElement(id);
// m_ElemLst.Add(elem);
//}
while (true)
{
Reference pickRef = commandData.Application.ActiveUIDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, new SelectionFilter(), "절단할 덕트 선택 : ");
XYZ Globalpt = pickRef.GlobalPoint;
if (pickRef == null) return Result.Cancelled;
Element elem = doc.GetElement(pickRef.ElementId);
using (Transaction trans = new Transaction(doc))
{
trans.Start("cutting");
XYZ sp = null, ep = null;
XYZ FlowVec = null, ReverseVec = null;
if (elem is Duct)
{
Util.GetStartEndPoint(elem as Duct, ref sp, ref ep);
Line ductline = ((elem as Duct).Location as LocationCurve).Curve as Line;
bool ChgSpEp = false;
//끝점과 가까우면 시작 끝점 바꾸기
if (Globalpt.DistanceTo(sp) > Globalpt.DistanceTo(ep))
{
XYZ PassPt = sp;
sp = ep;
ep = PassPt;
ChgSpEp = true;
}
FlowVec = (ep - sp).Normalize();
ReverseVec = (sp - ep).Normalize();
XYZ DirPt = sp;
Duct MainDuct = elem as Duct;
double UnionLength = 0;
while (true)
{
//자를 기준점
XYZ trimPt = Util.Polar(DirPt, FlowVec, Unit.MMToFeet(m_TrimDist));
//Util.Pyosi(doc, trimPt, 0);
//자를 기준점이 파이프를 넘어간 경우 작도 중지
Line divDuctLine = (MainDuct.Location as LocationCurve).Curve as Line;
XYZ onLinePt = Util.GetPointOnLine(divDuctLine, trimPt);
if (onLinePt.IsAlmostEqualTo(divDuctLine.GetEndPoint(0))
|| onLinePt.IsAlmostEqualTo(divDuctLine.GetEndPoint(1)))
break;
IntersectionResult interRes = ductline.Project(trimPt);
XYZ interResPt = interRes.XYZPoint;
//첫번째 유니온삽입 시 유니온 길이를 알 수 없어 50으로 정함
//두번째부터는 첫번째 넣은 유니온 길이를 구해 그 값보다 작으면 작도 X
//if (trimPt.DistanceTo(ep) < Unit.MMToFeet(10)) break;
if (UnionLength > 0)
{
if (trimPt.DistanceTo(ep) < UnionLength) break;
}
else
{
if (trimPt.DistanceTo(ep) < Unit.MMToFeet(50)) break;
}
List<ElementId> ElemIDLst = new List<ElementId>();
//파이프 자르기
ElemIDLst = Util.DivideElement(doc, MainDuct, trimPt);
if (ElemIDLst.Count() == 0) break;
//Util.Pyosi(doc, trimPt, 0);
DirPt = trimPt;
doc.Regenerate();
if (ChgSpEp == true)
{
MainDuct = doc.GetElement(ElemIDLst[0]) as Duct;
}
List<Connector> pipe1conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst[0]));
List<Connector> pipe2conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst[1]));
//자른 객체의 겹치는 커넥터에 유니온 피팅
foreach (Connector con1 in pipe1conlst)
{
foreach (Connector con2 in pipe2conlst)
{
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
{
//유니온 피팅
FamilyInstance famUnion = doc.Create.NewUnionFitting(con1, con2);
List<Connector> UnionConLst = Util.GetElementConnectors(famUnion);
if (UnionConLst.Count == 2)
{
UnionLength = UnionConLst[0].Origin.DistanceTo(UnionConLst[1].Origin);
}
//Util.Pyosi(doc, con1.Origin, 0);
//DirPt = con1.Origin;
doc.Regenerate();
//if (famUnion == null) NotDrawCnt++;
break;
}
}
}
}//while end
}
trans.Commit();
}
}//while end
//int NotDrawCnt = 0;
//using (Transaction trans = new Transaction(doc))
//{
// trans.Start("1");
// foreach (Element elem in m_ElemLst)
// {
// List<XYZ> m_DivPtLst = new List<XYZ>();
// XYZ sp = null, ep = null;
// XYZ FlowVec = null, ReverseVec = null;
//
// if (elem is Duct)
// {
// Util.GetStartEndPoint(elem as Duct, ref sp, ref ep);
// Line Ductline = ((elem as Duct).Location as LocationCurve).Curve as Line;
//
// FlowVec = (ep - sp).Normalize();
// ReverseVec = (sp - ep).Normalize();
//
// XYZ DirPt = sp;
// Duct mainDuct = elem as Duct;
//
// double UnionLength = 0;
// while (true)
// {
// //자를 기준점
// XYZ trimPt = Util.Polar(DirPt, FlowVec, Unit.MMToFeet(m_TrimDist));
// //자를 기준점이 덕트를 넘어간 경우 작도 중지
// Line divDuctLine = (mainDuct.Location as LocationCurve).Curve as Line;
// XYZ onLinePt = Util.GetPointOnLine(divDuctLine, trimPt);
//
// if (onLinePt.IsAlmostEqualTo(divDuctLine.GetEndPoint(0))
// || onLinePt.IsAlmostEqualTo(divDuctLine.GetEndPoint(1)))
// break;
//
// IntersectionResult interRes = Ductline.Project(trimPt);
// XYZ interResPt = interRes.XYZPoint;
// //첫번째 유니온삽입 시 유니온 길이를 알 수 없어 50으로 정함
// //두번째부터는 첫번째 넣은 유니온 길이를 구해 그 값보다 작으면 작도 X
// //if (trimPt.DistanceTo(ep) < Unit.MMToFeet(10)) break;
// if (UnionLength > 0)
// {
// if (trimPt.DistanceTo(ep) < UnionLength) break;
// }
// else
// {
// if (trimPt.DistanceTo(ep) < Unit.MMToFeet(50)) break;
// }
//
// //덕트 자르기
// List<ElementId> ElemIDLst = Util.DivideElement(doc, mainDuct, trimPt);
// DirPt = trimPt;
// if (ElemIDLst.Count() == 0) break;
//
// doc.Regenerate();
//
// List<Connector> duct1conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst[0]));
// List<Connector> duct2conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst[1]));
//
//
// //자른 객체의 겹치는 커넥터에 유니온 피팅
// foreach (Connector con1 in duct1conlst)
// {
// foreach (Connector con2 in duct2conlst)
// {
// if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
// {
// //유니온 피팅
// FamilyInstance famUnion = doc.Create.NewUnionFitting(con1, con2);
// List<Connector> UnionConLst = Util.GetElementConnectors(famUnion);
// if (UnionConLst.Count == 2)
// {
// UnionLength = UnionConLst[0].Origin.DistanceTo(UnionConLst[1].Origin);
// }
// //Util.Pyosi(doc, con1.Origin, 0);
// //DirPt = con1.Origin;
// doc.Regenerate();
//
// if (famUnion == null) NotDrawCnt++;
// break;
// }
// }
// }
//
// }//while end
// }
// }//foreach end
// trans.Commit();
//}
//
//if (NotDrawCnt > 0)
// MessageBox.Show("작도 실패 : " + NotDrawCnt + " 개", "결과");
}
catch (Exception)
{
//MessageBox.Show("" + e);
}
return Result.Succeeded;
}
/// <summary>
/// 유니온 피팅
/// </summary>
/// <param name="elem"></param> 덕트
/// <param name="divPt"></param> 자를 점 위치
/// <param name="TrimDist"></param> 1본 길이
/// <param name="NotDrawCnt"></param> 유니온 피팅 실패 갯수
/// <returns></returns>
public Connector FittingUnion(Element elem, XYZ divPt, double TrimDist, ref int NotDrawCnt)
{
Connector resCon = null;
try
{
Duct mainDuct = elem as Duct;
//파이프 자르기
List<ElementId> ElemIDLst = Util.DivideElement(doc, mainDuct, divPt);
if (ElemIDLst != null)
{
//List<Connector> famconlst = Util.GetElementConnectors(newFamily);
List<Connector> Duct1conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst.First()));
List<Connector> Duct2conlst = Util.GetElementConnectors(doc.GetElement(ElemIDLst[1]));
if (Duct1conlst[0].Origin.IsAlmostEqualTo(Duct1conlst[1].Origin, Unit.MMToFeet(0.01))) return null;
if (Duct2conlst[0].Origin.IsAlmostEqualTo(Duct2conlst[1].Origin, Unit.MMToFeet(0.01))) return null;
//자른 객체의 겹치는 커넥터에 유니온 피팅
foreach (Connector con1 in Duct1conlst)
{
foreach (Connector con2 in Duct2conlst)
{
if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01)))
{
//유니온 피팅
FamilyInstance famUnion = doc.Create.NewUnionFitting(con1, con2);
Transform familyTrans = famUnion.GetTransform();
List<Connector> famConLst = Util.GetElementConnectors(famUnion);
doc.Regenerate();
Connector Fsp = null, Fep = null, Ssp = null, Sep = null;
Util.GetStartEndConnector(doc.GetElement(ElemIDLst.First()) as Duct, ref Fsp, ref Fep);
Util.GetStartEndConnector(doc.GetElement(ElemIDLst[1]) as Duct, ref Ssp, ref Sep);
//유니온 장착 후 앞쪽 파이프 길이가 지정한 길이가 아니면 유니온 옮김
//if (Math.Abs(Fsp.Origin.DistanceTo(Fep.Origin) - Unit.MMToFeet(TrimDist * 1000)) > Unit.MMToFeet(0.01))
if (Math.Abs(Fsp.Origin.DistanceTo(Fep.Origin) - Unit.MMToFeet(TrimDist)) > Unit.MMToFeet(0.01))
{
if (Fsp.Origin.DistanceTo(Fep.Origin) - Unit.MMToFeet(TrimDist) < 0)
{
/*유니온 두개의 커넥터 사이기 길이 반만큼 이동해야 하기 때문에
뒤쪽 파이프 시작점으로 이동*/
XYZ translation = Ssp.Origin - familyTrans.Origin;
ElementTransformUtils.MoveElement(doc, famUnion.Id, translation);
doc.Regenerate();
//위치 변경 후 뒤쪽 파이프 시작점 리턴(시작점부터 다시 지정값만큼 이동해야 해서)
Util.GetStartEndConnector(doc.GetElement(ElemIDLst[1]) as Duct, ref Ssp, ref Sep);
//절단 길이 + 유니온 이동거리 > 남은 파이프 길이 = return
//if (Unit.MMToFeet(TrimDist * 1000) + (Ssp.Origin.DistanceTo(familyTrans.Origin)*3)
// > Ssp.Origin.DistanceTo(Sep.Origin)) return null;
resCon = Ssp;
break;
}
}
if (famUnion == null) NotDrawCnt++;
break;
}
}
}
}
}
catch
{
return resCon;
}
return resCon;
}
public class SelectionFilter : ISelectionFilter
{
public bool AllowElement(Element element)
{
if (element.Category == null) return false;
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves)
{
return true;
}
return false;
}
public bool AllowReference(Reference refer, XYZ point)
{
return false;
}
}
}
}