298 lines
11 KiB
C#
298 lines
11 KiB
C#
using Autodesk.Revit.UI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Autodesk.Revit.DB;
|
|
using Autodesk.Revit.UI.Selection;
|
|
using System.Threading.Tasks;
|
|
using KDCS.Utils;
|
|
using System.Collections;
|
|
using System.Windows.Forms;
|
|
using Autodesk.Revit.DB.Plumbing;
|
|
using Autodesk.Revit.DB.Mechanical;
|
|
using System.Xml.Linq;
|
|
using Autodesk.Revit.UI.Events;
|
|
using System.IO;
|
|
using KMBIM.Revit.Tools;
|
|
using KMBIM.Revit.Tools.Cmd.SyncPipe;
|
|
|
|
/// <summary>
|
|
/// 단열재를 선택적으로 고려하며 기준 배관의 간격 띄우기 값을 기준으로 나머지 선택한 배관(들)의 높이를 통일 시킨다.
|
|
/// Sync pipe's offset with criteria pipe that user selected.
|
|
/// Made By 이주호(Lee Juho), DCS Company, South Korea
|
|
/// 2021.07.09 ~ 2021.07.13
|
|
/// </summary>
|
|
|
|
namespace KMBIM
|
|
{
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|
|
|
/*
|
|
1. 간격띄우기 값 바꿀 배관(들) 선택
|
|
2. 기준 배관 선택
|
|
3. winForm 띄워서 기준점 선택
|
|
4. 선택 받은 기준점을 토대로 연산해서 배관 간격띄우기 값 편집
|
|
*/
|
|
|
|
public class SyncPipe : IExternalCommand
|
|
{
|
|
UIApplication uiapp;
|
|
UIDocument uidoc;
|
|
Autodesk.Revit.DB.Document doc = null;
|
|
Autodesk.Revit.ApplicationServices.Application app = null;
|
|
|
|
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
|
{
|
|
try
|
|
{
|
|
//if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
|
|
// Verify active document
|
|
if (null == commandData.Application.ActiveUIDocument.Document)
|
|
{
|
|
message = "현재 활성화된 뷰가 없습니다.";
|
|
return Result.Failed;
|
|
}
|
|
|
|
uiapp = commandData.Application;
|
|
uidoc = uiapp.ActiveUIDocument;
|
|
app = uiapp.Application;
|
|
doc = uidoc.Document;
|
|
|
|
List<Pipe> pList = new List<Pipe>();
|
|
|
|
IList<Reference> rList = uidoc.Selection.PickObjects(ObjectType.Element, new PipeSelectionFilter(), "위치 바꿀 배관 선택: ");
|
|
foreach(Reference r in rList)
|
|
{
|
|
if (r == null) return Result.Cancelled;
|
|
|
|
Pipe movePipe = doc.GetElement(r.ElementId) as Pipe;
|
|
pList.Add(movePipe);
|
|
}
|
|
|
|
//위치 바꿀 배관 간격 띄우기, 외경 파라미터 구하기
|
|
List<Parameter> movePipeParamList = new List<Parameter>();
|
|
List<double> movePipeOffsetParamList = new List<double>();
|
|
List<double> movePipeOuterDiaParamList = new List<double>();
|
|
List<double> movePipeInsultionParamList = new List<double>();
|
|
|
|
List<mvPipeData> mpdList = new List<mvPipeData>();
|
|
|
|
foreach (Pipe p in pList)
|
|
{
|
|
if (p == null)//선택한 것이 파이프가 아니면 패스
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Parameter mvPipeOffsetParam = p.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM);//간격 띄우기
|
|
double mvPipeOffset = mvPipeOffsetParam.AsDouble();
|
|
|
|
Parameter mvPipeODiaParam = p.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);//외경
|
|
double mvPipeODia = mvPipeODiaParam.AsDouble();
|
|
|
|
Parameter mvPipeInsulTickParam = p.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);//단열재 두께
|
|
double mvPipeInsulTick = mvPipeInsulTickParam.AsDouble();
|
|
|
|
movePipeParamList.Add(mvPipeOffsetParam);
|
|
movePipeOffsetParamList.Add(mvPipeOffset);
|
|
movePipeOuterDiaParamList.Add(mvPipeODia);
|
|
|
|
//클래스를 사용해서 한 세트로
|
|
mvPipeData mpd = new mvPipeData();
|
|
|
|
mpd.Id = p.Id;
|
|
mpd.Od = mvPipeODia;
|
|
mpd.InsultionTick = mvPipeInsulTick;
|
|
mpd.Param = mvPipeOffsetParam;
|
|
|
|
//배열로 쌓기
|
|
mpdList.Add(mpd);
|
|
}
|
|
|
|
//기준 배관에서 필요한 데이터 추출---------------------------------------------------------------------------------------------------------
|
|
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, new PipeSelectionFilter(), "기준 배관 선택: ");
|
|
Pipe criteriaPipe = doc.GetElement(refer.ElementId) as Pipe;
|
|
|
|
if (criteriaPipe == null)
|
|
{
|
|
MessageBox.Show("기준은 배관이여야 합니다.", "오류");
|
|
return Result.Failed;
|
|
}
|
|
|
|
Autodesk.Revit.DB.Parameter criteriaPipeOffestParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM);
|
|
double criteriaPipeOffset = criteriaPipeOffestParam.AsDouble();
|
|
|
|
Autodesk.Revit.DB.Parameter criteriaOuterDiaParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
|
|
double criteriaOuterDia = criteriaOuterDiaParam.AsDouble();
|
|
|
|
Parameter insulationParam = criteriaPipe.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
|
|
double criteriaInsultion = insulationParam.AsDouble();
|
|
//------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
SelectLocation sl = new SelectLocation();
|
|
|
|
sl.ShowDialog();
|
|
|
|
|
|
if(sl.ccValue == 1)//윈폼에서 Cancel 누른 경우 명령 취소
|
|
{
|
|
return Result.Cancelled;
|
|
}
|
|
|
|
//유저가 winForm에서 선택한 원하는 위치값 구하기
|
|
double newPipeOffset = GetLocationByUserInput(sl.insulValue, sl.value, criteriaPipeOffset, criteriaOuterDia, criteriaInsultion);
|
|
|
|
using (Transaction tr = new Transaction(doc))
|
|
{
|
|
tr.Start("start");
|
|
|
|
double mvPipeLoc = 0;
|
|
|
|
//선택한 배관(들)의 배치점 구하기.(위에서 구한 위치값으로 간격띄우기값을 조정하면 기준 선에 배관이 정렬되지 않기 때문)
|
|
foreach (var a in mpdList)
|
|
{
|
|
//단열재 등의 고려사항을 다 연산해서 배치점 구하기
|
|
mvPipeLoc = GetMovePipeLocation(sl.insulValue, sl.value, a.InsultionTick, newPipeOffset, a.Od);
|
|
|
|
a.Param.Set(mvPipeLoc);
|
|
}
|
|
|
|
tr.Commit();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
//MessageBox.Show(e.Message);
|
|
}
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
|
|
//기준 Offset구하기
|
|
public double GetLocationByUserInput(int insultion, int value, double criteriaPipeOffset, double criteriaOuterDia, double insultionTick)
|
|
{
|
|
double newPipeOffset = 0;
|
|
|
|
switch (insultion)
|
|
{
|
|
case (1)://단열재 고려 X
|
|
switch (value)
|
|
{
|
|
case (1):
|
|
newPipeOffset = criteriaPipeOffset + (criteriaOuterDia / 2);//상부 일치
|
|
break;
|
|
|
|
case (2):
|
|
newPipeOffset = criteriaPipeOffset;//중간 일치
|
|
break;
|
|
|
|
case (3):
|
|
newPipeOffset = criteriaPipeOffset - (criteriaOuterDia / 2);//하부 일치
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case (2)://단열재 고려 O
|
|
switch (value)
|
|
{
|
|
case (1):
|
|
newPipeOffset = criteriaPipeOffset + ((criteriaOuterDia / 2) + insultionTick);
|
|
break;
|
|
|
|
case (2):
|
|
newPipeOffset = criteriaPipeOffset + insultionTick;
|
|
break;
|
|
|
|
case (3):
|
|
newPipeOffset = criteriaPipeOffset - ((criteriaOuterDia / 2) + insultionTick);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return newPipeOffset;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 값 계산해서 이동할 배관들 배치점 찾기
|
|
/// </summary>
|
|
/// <param name="insulValue">wimForm에서 선택한 단열재 고려 여부</param>
|
|
/// <param name="value">winForm에서 선택한 기준 배치점 위치(상중하)</param>
|
|
/// <param name="insultionTick">단열재 두께</param>
|
|
/// <param name="newPipeOffset">기준 배치점</param>
|
|
/// <param name="od">내경</param>
|
|
/// <returns></returns>
|
|
public double GetMovePipeLocation(int insulValue, int value, double insultionTick, double newPipeOffset, double od)
|
|
{
|
|
double mvPipeLoc = 0;
|
|
|
|
switch (insulValue)
|
|
{
|
|
case (1)://단열제 미고려
|
|
switch (value)
|
|
{
|
|
case (1):
|
|
mvPipeLoc = newPipeOffset - (od / 2 );//상부
|
|
break;
|
|
|
|
case (2):
|
|
mvPipeLoc = newPipeOffset;//중간
|
|
break;
|
|
|
|
case (3):
|
|
mvPipeLoc = newPipeOffset + (od / 2);//하부
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case (2)://단열재 고려
|
|
switch (value)
|
|
{
|
|
case (1):
|
|
mvPipeLoc = newPipeOffset - (od / 2 + insultionTick);//상부
|
|
break;
|
|
|
|
case (2):
|
|
mvPipeLoc = newPipeOffset;//중간
|
|
break;
|
|
|
|
case (3):
|
|
mvPipeLoc = newPipeOffset + (od / 2 + insultionTick);//하부
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return mvPipeLoc;
|
|
}
|
|
|
|
public class PipeSelectionFilter : ISelectionFilter
|
|
{
|
|
public bool AllowElement(Element element)
|
|
{
|
|
if (element.Category == null) return false;
|
|
|
|
if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool AllowReference(Reference refer, XYZ point)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class mvPipeData
|
|
{
|
|
public ElementId Id { get; set; }
|
|
public double Od { get; set; }
|
|
public double InsultionTick { get; set; }
|
|
public Parameter Param { get; set; }
|
|
}
|
|
}
|