Client/Desktop/KMBIM3.0/KMBIM3.0_소스/Cmd/MatchProp/MatchProp.cs

470 lines
19 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 KMBIM.Revit.Tools.Cmd.MatchProp;
using KDCS.Utils;
using System.Collections;
using System.Windows.Forms;
using KMBIM.Revit.Tools;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Mechanical;
namespace KMBIM
{
[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 MatchProp : IExternalCommand
{
private UIApplication uiapp = null;
private UIDocument uidoc = null;
private Autodesk.Revit.ApplicationServices.Application app = null;
private Document doc = null;
public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
{
try
{
if (!WorkMain.GetInstance().IsValid) return Autodesk.Revit.UI.Result.Succeeded;
Element eSrc = null;
// 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;
// 선택한 패밀리요소로부터 파라미터를 복사합니다.
try
{
var r = uidoc.Selection.PickObject(ObjectType.Element, "파라미터를 복사할 기준 패밀리 선택: ");
if (r == null) return Result.Succeeded;
eSrc = doc.GetElement(r.ElementId);
if (eSrc != null)
{
FormSelectParameter1 wf = new FormSelectParameter1(eSrc);
wf.ShowDialog();
}
}
catch (OperationCanceledException)
{
return Result.Cancelled;
}
if (eSrc != null)
{
// 파라미터 복사(리스트박스-다중선택)
FormSelectParameter1 wf = new FormSelectParameter1(eSrc);
}
if (eSrc == null)// 파라미터를 복사한 경우에만 처리
{
MessageBox.Show("이 명령을 실행하기 전에 매개변수를 복사해야 합니다.");
return Result.Failed;
}
if (eSrc.IsValidObject != true) // 복사한 파라미터의 소유자(패밀리요소)가 삭제되어 유효하지 않는 경우
{
MessageBox.Show("복사한 파라미터의 소유자(패밀리요소)가 더이상 유효하지 않습니다.");
return Result.Failed;
}
var wm = WorkMain.GetInstance();
eSrc = wm.CopiedParametersElement;
var ListElementParameter = wm.CopiedParameters; // 복사한 파라미터
// 복사 대상 요소 선택
string msg = "매개변수 값을 붙여넣을 패밀리 선택: ";
List<Element> eList = SelectMultipleElements(uidoc, doc, msg);
List<Parameter> pa = new List<Parameter>();
if (eList == null) return Result.Succeeded;
pa = GetCopyParameterList(eList);//바뀐 파이프와 덕트 정보 가져오기(파이프: 관경 / 덕트: 높이, 폭, 관경)
//레듀셔를 선택하더라도 리스트에서 제외
List<Element> last = new List<Element>();
foreach (Element eTarget in eList)
{
if (GetFamilyPartType(eTarget, PartType.Transition) || eTarget is Level)
{
continue;
}
else
{
last.Add(eTarget);
}
}
using (Transaction tx = new Transaction(doc))
{
tx.Start("update-parameter-value");
foreach (Element eTarget in last)
{
if (eTarget == null) return Result.Succeeded;
doc.Regenerate();
if (eTarget == eSrc) continue;
Hashtable htTargetParameters = new Hashtable();
FamilyInstance famInst = null;
var parameters = eTarget.GetOrderedParameters().ToList();
//예외 선언
if (eSrc is Pipe && eTarget is Duct)
{
MessageBox.Show("파이프 특성을 덕트에 매치할 수 없습니다.", "오류");
return Result.Succeeded;
}
else if (eSrc is Duct && eTarget is Pipe)
{
MessageBox.Show("덕트 특성을 파이프에 매치할 수 없습니다.", "오류");
return Result.Succeeded;
}
if (eTarget is Pipe || eTarget is Duct || eTarget.Category.Name.ToString() == "배관 부속류" ||
eTarget.Category.Name.ToString() == "덕트 부속류")
{
if (Util.GetFamilyPartType(eTarget, PartType.Transition))
{
continue;
}
}
// 복사 대상 파라미터
htTargetParameters.Clear();
foreach (var p in parameters)
{
string strGroup = LabelUtils.GetLabelFor(p.Definition.ParameterGroup);
string strGropAndParameterName = strGroup + "/" + p.Definition.Name;
if (htTargetParameters.Contains(strGropAndParameterName) == false)
{
htTargetParameters.Add(strGropAndParameterName, p);
}
}
// 기준 요소의 파라미터 값을 대상 요소의 파라미터에 복사한다.
foreach (Parameter p in ListElementParameter)// 기준 요소 파라미터
{
string strGroup = LabelUtils.GetLabelFor(p.Definition.ParameterGroup);
string defName = p.Definition.Name;
string strGropAndParameterName = strGroup + "/" + defName;
object oParam = htTargetParameters[strGropAndParameterName];
if (oParam != null)
{
Parameter curParam = oParam as Parameter;
if (curParam.IsReadOnly == false && strGroup.Contains("ID") == false)//쓸데없는 정보 안띄우기
{
Util.SetParameterValue(curParam, Util.GetParameterValue(p));// 붙혀넣기
}
}
//덕트나 파이프 수정
if (eSrc is Pipe || eSrc is Duct || eSrc is FamilyInstance)
{
if (eTarget is Pipe || eTarget is Duct || eTarget is FamilyInstance)
{
List<Connector> conList = new List<Connector>();
conList = Util.GetElementConnectors(eTarget);//모든 커넥터 가져오기
if (defName == "지름" || defName == "높이" || defName == "폭")
{
if (eTarget is FamilyInstance)
{
famInst = eTarget as FamilyInstance;
foreach (Connector c in conList)//커넥터의 Owner 파악하기
{
//파이프 수정
ChangePipeProperties(eTarget, pa, famInst);
//덕트 수정
ChangeDuctProperties(eTarget, pa, famInst);
}
}
}
}
}
}
}
tx.Commit();
}//end - Transition
}
catch (Exception ex)
{
//message = ex.ToString();
return Result.Failed;
}
return Result.Succeeded;
}
#region Element Selection
public static Element SelectSingleElement(UIDocument uidoc, string description)
{
if (ViewType.Internal == uidoc.ActiveView.ViewType)
{
string msg = "현재 보기에서 요소를 선택할 수 없습니다.";
TaskDialog.Show("Error", msg + uidoc.ActiveView.Name);
return null;
}
try
{
Reference r = uidoc.Selection.PickObject(ObjectType.Element, description);
return uidoc.Document.GetElement(r);
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return null;
}
}
public static List<Element> SelectMultipleElements(UIDocument uidoc, Document doc, string description)
{
if (ViewType.Internal == uidoc.ActiveView.ViewType)
{
string msg = "현재 보기에서 요소를 선택할 수 없습니다,";
TaskDialog.Show("Error", msg + uidoc.ActiveView.Name);
}
List<Element> SelElemList = new List<Element>();
try
{
IList<Reference> r = new List<Reference>();
r = uidoc.Selection.PickObjects(ObjectType.Element, description);
foreach (Reference Ref in r)
{
//SelElem = doc.GetElement(Ref.ElementId) as Element;
SelElemList.Add(doc.GetElement(Ref.ElementId) as Element);
}
return SelElemList;
}
catch
{
return null;
}
}
/// <summary>
/// 붙혀넣을 패밀리에 BuiltInParameter값이 없는 경우 복사한 파라미터 값 넣기
/// </summary>
/// <param name="p">복사한 파라미터</param>
/// <param name="targetFamily">target 패밀리</param>
/// <param name="targeParameterName">target 파라미터 이름</param>
/// <param name="isRadius">target 파라미터가 반지름인지 여부</param>
public void SetParameterValue(Parameter copyParam, FamilyInstance targetFamily, string targeParameterName, bool isRadius)
{
Parameter targetParam = targetFamily.LookupParameter(targeParameterName);//targetParameterName 찾기
if (targetParam != null)
{
if (isRadius == true)//targetParameter가 반지름일 경우에 나누기 2
{
targetParam.Set(copyParam.AsDouble() / 2);
}
else
{
targetParam.Set(copyParam.AsDouble());
}
}
}
public List<Parameter> GetCopyParameterList(List<Element> eList)
{
List<Parameter> paramList = new List<Parameter>();
foreach (Element eTarget in eList)
{
if (eTarget is Pipe)//파이프인 경우
{
Parameter pipeParam = eTarget.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);//관경
paramList.Add(pipeParam);
}
else if (eTarget is Duct)//덕트인 경우
{
//바뀐 덕트 정보 가져오기
Parameter ductHeightParam = eTarget.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);//높이
Parameter ductWidthParam = eTarget.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);//폭
Parameter ductDiameterParam = eTarget.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);//관경(원형덕트)
if (ductHeightParam != null)
{
paramList.Add(ductHeightParam);
}
if (ductWidthParam != null)
{
paramList.Add(ductWidthParam);
}
if (ductDiameterParam != null)//원형덕트
{
paramList.Add(ductDiameterParam);
}
}
}
return paramList;
}
//패밀리의 타입구분
public static bool GetFamilyPartType(Element element, PartType partType)
{
List<Connector> ConLst = GetElementConnectors(element);
if (ConLst == null || ConLst.Count() <= 0) return false;
Connector baseCon = ConLst.First();
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;
}
//객체의 커넥터 구하기.(파이프,덕트,패밀리)
public static List<Connector> GetElementConnectors(Element elem)
{
List<Connector> ConLst = new List<Connector>();
ConnectorSet connectorSet = null;
if (elem is Pipe)
connectorSet = (elem as Pipe).ConnectorManager.Connectors;
else if (elem is Duct)
connectorSet = (elem as Duct).ConnectorManager.Connectors;
else if (elem is FamilyInstance)
connectorSet = (elem as FamilyInstance).MEPModel.ConnectorManager.Connectors;
if (connectorSet == null) return null;
foreach (Connector con in connectorSet)
{
ConLst.Add(con);
}
return ConLst;
}
public void ChangePipeProperties(Element eTarget, List<Parameter> pa, FamilyInstance famInst)
{
if (eTarget.Category.Name.ToString() == "배관 부속류")//Pipe부속인 경우
{
foreach (Parameter pm in pa)
{
Parameter param = famInst.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
PartType partType = (PartType)param.AsInteger();
switch (partType.ToString())
{
case "Elbow":
SetParameterValue(pm, famInst, "공칭 반지름", true);
break;
case "Tee":
SetParameterValue(pm, famInst, "공칭 반지름", true);
break;
case "Cross":
SetParameterValue(pm, famInst, "공칭 반지름", true);
break;
case "Wye":
SetParameterValue(pm, famInst, "공칭 반지름", true);
break;
}
}
}
}
public void ChangeDuctProperties(Element eTarget, List<Parameter> pa, FamilyInstance famInst)
{
if (eTarget.Category.Name.ToString() == "덕트 부속")//덕트 부속인 경우
{
Parameter param = famInst.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_CONTENT_PART_TYPE);
PartType partType = (PartType)param.AsInteger();
switch (partType.ToString())
{
case "Elbow":
if (famInst.LookupParameter("덕트 높이") != null)
{
SetParameterValue(pa[0], famInst, "덕트 높이", false);
}
if (famInst.LookupParameter("덕트 폭") != null)
{
SetParameterValue(pa[1], famInst, "덕트 폭", false);
}
if (famInst.LookupParameter("덕트 반지름") != null)
{
SetParameterValue(pa[0], famInst, "덕트 반지름", true);
}
break;
case "Tee":
if (famInst.LookupParameter("덕트 높이") != null)
{
SetParameterValue(pa[0], famInst, "덕트 높이", false);
}
if (famInst.LookupParameter("덕트 폭") != null)
{
SetParameterValue(pa[1], famInst, "덕트 폭", false);
}
if (famInst.LookupParameter("덕트 반지름 1") != null)
{
SetParameterValue(pa[0], famInst, "덕트 반지름 1", true);
}
break;
case "Damper":
if (famInst.LookupParameter("덕트 높이") != null)
{
SetParameterValue(pa[0], famInst, "덕트 높이", false);
}
if (famInst.LookupParameter("덕트 폭") != null)
{
SetParameterValue(pa[1], famInst, "덕트 폭", false);
}
break;
}
}
else if(eTarget.Category.Name.ToString() == "덕트 액세서리")
{
if (famInst.LookupParameter("덕트 높이") != null)
{
SetParameterValue(pa[0], famInst, "덕트 높이", false);
}
if (famInst.LookupParameter("덕트 폭") != null)
{
SetParameterValue(pa[1], famInst, "덕트 폭", false);
}
}
}
}
#endregion
}