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 eList = SelectMultipleElements(uidoc, doc, msg); List pa = new List(); if (eList == null) return Result.Succeeded; pa = GetCopyParameterList(eList);//바뀐 파이프와 덕트 정보 가져오기(파이프: 관경 / 덕트: 높이, 폭, 관경) //레듀셔를 선택하더라도 리스트에서 제외 List last = new List(); 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 conList = new List(); 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 SelectMultipleElements(UIDocument uidoc, Document doc, string description) { if (ViewType.Internal == uidoc.ActiveView.ViewType) { string msg = "현재 보기에서 요소를 선택할 수 없습니다,"; TaskDialog.Show("Error", msg + uidoc.ActiveView.Name); } List SelElemList = new List(); try { IList r = new List(); 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; } } /// /// 붙혀넣을 패밀리에 BuiltInParameter값이 없는 경우 복사한 파라미터 값 넣기 /// /// 복사한 파라미터 /// target 패밀리 /// target 파라미터 이름 /// target 파라미터가 반지름인지 여부 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 GetCopyParameterList(List eList) { List paramList = new List(); 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 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 GetElementConnectors(Element elem) { List ConLst = new List(); 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 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 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 }