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 SpinKler; using Autodesk.Revit.DB.Plumbing; using KDCS.Utils; using Autodesk.Revit.DB.Structure; using KMBIM.Revit.Tools.Cmd.SprinklerConnect; using KMBIM.Revit.Tools; namespace KMBIM { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] class Sprinkler_Upword_Manual : 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; double m_MainHgt = 0, m_BranchHgt = 0, m_CapDist = 0, m_Tol = 0, m_TReducerDist = 0; Connector mainSpCon = null, mainEpCon = null; XYZ MainVec = null; List lst_objSprinkler = new List(); ObjSprinKler FirstObj = new ObjSprinKler(); SprinKler_Function Spkr_Func = new SprinKler_Function(); List RemoveElemIdLst = new List(); 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; try { //메인 파이프 Reference pickMainRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionMainPipe(), "기준 교차배관 선택 : "); if (pickMainRef == null) return Result.Succeeded; Element MainElem = doc.GetElement(pickMainRef.ElementId) as Element; Pipe mainPipe = MainElem as Pipe; Line mainLine = (mainPipe.Location as LocationCurve).Curve as Line; XYZ DirectVec = null, ReverseVec = null; DirectVec = (mainLine.GetEndPoint(1) - mainLine.GetEndPoint(0)).Normalize(); ReverseVec = (mainLine.GetEndPoint(0) - mainLine.GetEndPoint(1)).Normalize(); XYZ SpExtension = Util.Polar(mainLine.GetEndPoint(0), ReverseVec, 1000); XYZ EpExtension = Util.Polar(mainLine.GetEndPoint(1), DirectVec, 1000); Line NewMainLine = Line.CreateBound(SpExtension, EpExtension); Util.GetStartEndConnector(mainPipe, ref mainSpCon, ref mainEpCon);//메인 시작 끝 커넥터 //m_MainHgt = NewMainLine.GetEndPoint(0).Z;//메인 높이 m_MainHgt = mainPipe.LevelOffset;//메인 파이프 오프셋 값 //현재 레벨의 높이 구하기.(active Level을 구하면 3D에서 작도가 안됌.) double GenLevElevation = Unit.FeetToMM(NewMainLine.GetEndPoint(0).Z - mainPipe.LevelOffset); MainVec = (mainEpCon.Origin - mainSpCon.Origin).Normalize();//메인 시작-끝 벡터 //처음 관경25는 헤드쪽때문에 기입 List headDiaLst = new List(); headDiaLst.Add(25); headDiaLst.Add(25); headDiaLst.Add(25); headDiaLst.Add(32); headDiaLst.Add(40); headDiaLst.Add(40); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(50); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); headDiaLst.Add(65); //대화상자 Form_Upward dlg = new Form_Upward(); dlg.MainHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3); dlg.BranchHeight = Math.Round(Unit.FeetToMM(m_MainHgt), 3) + 300; dlg.CapDist = 100; dlg.SpkrTol = 5; dlg.TeeReducerDist = 100; dlg.ShowDialog(); if (dlg.DialogResult == DialogResult.Cancel) return Result.Cancelled; //대화상자 값 가져오기 m_MainHgt = dlg.MainHeight; m_BranchHgt = dlg.BranchHeight; m_CapDist = dlg.CapDist; m_Tol = dlg.SpkrTol; m_TReducerDist = dlg.TeeReducerDist; //교차배관,가지배관 높이 재지정 m_MainHgt = m_MainHgt + GenLevElevation; m_BranchHgt = m_BranchHgt + GenLevElevation; //SprinKler_Function 변수값 넘겨주기 Spkr_Func.doc = uidoc.Document; Spkr_Func.creDoc = doc.Create; Spkr_Func.uiapp = commandData.Application; Spkr_Func.MainPipeTypeId = mainPipe.PipeType.Id; Spkr_Func.MainSystemTypeId = mainPipe.MEPSystem.GetTypeId(); Spkr_Func.MainLevelId = mainPipe.ReferenceLevel.Id; //MessageBox.Show("메인 높이 : " + m_MainHgt + "\n헤드 오프셋 : " + m_HeadOffset + "\n캡 거리 : " + m_CapDist); //첫번째 헤드 while (true) { Reference pickFirstRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "스프링클러 헤드 선택 : "); if (pickFirstRef == null) return Result.Succeeded; Element pickFirstElem = doc.GetElement(pickFirstRef.ElementId); if (pickFirstElem is FamilyInstance) { FamilyInstance firstHeadfam = pickFirstElem as FamilyInstance; List ConLst = Util.GetElementConnectors(firstHeadfam); //헤드 커넥터 Connector HeadCon = ConLst.First(); //첫번째 헤드의 커넥터가 가지배관 높이 + 100보다 //if (HeadCon.Origin.Z < Unit.MMToFeet(m_BranchHgt + 100)) if (HeadCon.Origin.Z < Unit.MMToFeet(Math.Round(m_BranchHgt, 3) + 60)) { MessageBox.Show("스프링클러 헤드가 가지배관 높이보다 낮아 작도할 수 없습니다.", "오류"); continue; } //메인관-커넥터 가까운 점 IntersectionResult interRes = NewMainLine.Project(HeadCon.Origin); XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, HeadCon.Origin.Z); //첫번째 헤드 정보 FirstObj.HeadCon = HeadCon; FirstObj.m_Headpt = HeadCon.Origin; FirstObj.m_InterPt = interPt; FirstObj.m_SpID = firstHeadfam.Id; lst_objSprinkler.Add(FirstObj); break; } }//while end ObjSprinKler objspkr = new ObjSprinKler(); objspkr = FirstObj; //두번째 헤드부터 반복문 List BranchPtLst = new List(); int sp_in = 0; int HeadCnt = 1; while (true) { Reference pickRef = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "스프링클러 헤드 선택 : "); Element pickElem = doc.GetElement(pickRef.ElementId); //헤드 선택했을 때 if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers) { FamilyInstance Headfamily = pickElem as FamilyInstance; List ConLst = Util.GetElementConnectors(Headfamily); //헤드 커넥터 Connector HeadCon = ConLst.First(); if (HeadCon.Origin.Z < Unit.MMToFeet(Math.Round(m_BranchHgt, 3) + 60)) { MessageBox.Show("스프링클러 헤드가 가지배관 높이보다 낮아 작도할 수 없습니다.", "오류"); continue; } //메인관-커넥터 가까운 점 IntersectionResult interRes = NewMainLine.Project(HeadCon.Origin); XYZ interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, HeadCon.Origin.Z); ObjSprinKler NextObjSpkr = new ObjSprinKler(); //헤드 정보 NextObjSpkr.HeadCon = HeadCon; NextObjSpkr.m_Headpt = HeadCon.Origin; NextObjSpkr.m_InterPt = interPt; NextObjSpkr.m_SpID = Headfamily.Id; List pipeLst = new List(); using (Transaction trans = new Transaction(doc)) { trans.Start("1"); { double firstDist = objspkr.m_InterPt.DistanceTo(mainLine.GetEndPoint(1)); double nextDist = NextObjSpkr.m_InterPt.DistanceTo(mainLine.GetEndPoint(1)); double dist = Unit.FeetToMM(firstDist - nextDist); //첫번째 두번째 스프링클러의 거리가 허용오차 보다 작으면 옮김. if (Math.Abs(firstDist - nextDist) <= Unit.MMToFeet(m_Tol)) { //using(Transaction trans = new Transaction(doc)) //{ // trans.Start("SortSpkr"); XYZ moveVec = (objspkr.m_InterPt - NextObjSpkr.m_InterPt).Normalize(); XYZ movePt = Util.Polar(NextObjSpkr.m_Headpt, moveVec, Math.Abs(firstDist - nextDist)); FamilyInstance family = doc.GetElement(NextObjSpkr.m_SpID) as FamilyInstance; LocationPoint locpt = family.Location as LocationPoint; locpt.Point = movePt; doc.Regenerate(); List conLst = Util.GetElementConnectors(family); Connector MoveHeadCon = ConLst.First(); //메인관-커넥터 가까운 점 interRes = NewMainLine.Project(MoveHeadCon.Origin); interPt = new XYZ(interRes.XYZPoint.X, interRes.XYZPoint.Y, MoveHeadCon.Origin.Z); //헤드 정보 NextObjSpkr.HeadCon = MoveHeadCon; NextObjSpkr.m_Headpt = MoveHeadCon.Origin; NextObjSpkr.m_InterPt = interPt; NextObjSpkr.m_SpID = Headfamily.Id; // trans.Commit(); //} } } lst_objSprinkler.Add(NextObjSpkr); List pts = Spkr_Func.UpSPJOIN(objspkr, NextObjSpkr, m_BranchHgt, ref sp_in, HeadCnt, headDiaLst); if (pts == null) continue; XYZ objSpkr_offsetpt = new XYZ(objspkr.m_Headpt.X, objspkr.m_Headpt.Y, Unit.MMToFeet(m_BranchHgt)); XYZ NextobjSpkr_offsetpt = new XYZ(NextObjSpkr.m_Headpt.X, NextObjSpkr.m_Headpt.Y, Unit.MMToFeet(m_BranchHgt)); if (pts.Count() == 2) { BranchPtLst.AddRange(pts); } List DrawPts = new List(); DrawPts.Add(objSpkr_offsetpt); DrawPts.AddRange(pts); DrawPts.Add(NextobjSpkr_offsetpt); pipeLst = Util.CreatePipe(uiapp, doc, DrawPts, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId); trans.Commit(); } //지울 객체 찾아서 마무리에서 삭제할 리스트에 담기 List RemoveIDLst = Spkr_Func.getFamilyAndPipe(pipeLst.First()); RemoveElemIdLst.AddRange(RemoveIDLst); HeadCnt++; objspkr = NextObjSpkr; } //파이프(메인) 선택했을 때 else if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) { Pipe PickMainPipe = pickElem as Pipe; //이전에 작도된 파이프와 엘보는 삭제하고 작업 Util.DeleteElement(doc, RemoveElemIdLst); //지운 객체를 밖에서 또 지우기 때문에 리스트 비움 RemoveElemIdLst.Clear(); ////double minDrawHgt = FirstObj.m_Headpt.Z + Unit.MMToFeet(m_HeadOffset) + (mainEpCon.Radius * 3); //double betweenHgt = Math.Abs(FirstObj.m_Headpt.Z - mainEpCon.Origin.Z); //double minDrawHgt = Unit.MMToFeet(m_HeadOffset) + (mainEpCon.Radius * 3); // //double aa = Unit.FeetToMM(betweenHgt); //double bb = Unit.FeetToMM(minDrawHgt); //if (betweenHgt < minDrawHgt) //{ // MessageBox.Show("메인 파이프와 헤드 사이에 작도할 높이가 좁습니다."); // break; //} XYZ CapPt = Spkr_Func.GetCAPpoint(FirstObj, m_BranchHgt, m_CapDist); //캡 포인트 리스트 담기 if (BranchPtLst.Count() > 0) { //리스트에 값이 있으면 처음에 pt넣음 BranchPtLst.Reverse(); BranchPtLst.Add(CapPt); BranchPtLst.Reverse(); } else BranchPtLst.Add(CapPt); //메인 연결될 가지파이프 XYZ LastPt = Spkr_Func.GetMain2LastpipePoint(objspkr, m_BranchHgt); BranchPtLst.Add(LastPt); List ElemIdLst = new List(); using (Transaction trans = new Transaction(doc)) { trans.Start("1"); List DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId); //헤드 가지배관 연결 ElemIdLst = Spkr_Func.ConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst,m_TReducerDist); trans.Commit(); } using (Transaction trans = new Transaction(doc)) { trans.Start("1"); //교차배관 가지배관 연결 MainConnectElbow(MainElem, doc.GetElement(ElemIdLst.Last())); trans.Commit(); } break; } //엘보를 선택했을 때 else if (pickElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting) { FamilyInstance ElbowFamily = pickElem as FamilyInstance; string elbowFamStr = ElbowFamily.Category.Name; Line ExtensionLine = NewMainLine; //이전에 작도된 파이프와 엘보는 삭제하고 작업 Util.DeleteElement(doc, RemoveElemIdLst); //지운 객체를 밖에서 또 지우기 때문에 리스트 비움 RemoveElemIdLst.Clear(); //캡 생성 XYZ CapPt = Spkr_Func.GetCAPpoint(FirstObj, m_BranchHgt, m_CapDist); //캡 포인트 리스트 담기 if (BranchPtLst.Count() > 0) { //리스트에 값이 있으면 처음에 pt넣음 BranchPtLst.Reverse(); BranchPtLst.Add(CapPt); BranchPtLst.Reverse(); } else BranchPtLst.Add(CapPt); //메인 연결될 가지파이프 XYZ LastPt = Spkr_Func.GetMain2LastpipePoint(objspkr, m_BranchHgt); BranchPtLst.Add(LastPt); List ElemIdLst = new List(); //가지배관 헤드 연결 using (Transaction trans = new Transaction(doc)) { trans.Start("HeadConnectBranch"); List DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId); //헤드 가지배관 연결 ElemIdLst = Spkr_Func.ConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst, m_TReducerDist); //교차배관 가지배관 연결 //MainConnectElbow(MainElem, doc.GetElement(ElemIdLst.Last())); trans.Commit(); } // //XYZ InterPt = Util.GetPointOnLine(ExtensionLine, LastPt); ////Util.Pyosi(doc, InterPt, 1); // ////생성되어있는 T 찾기 //FamilyInstance CrossTee = null; // //IList instances = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).ToElements(); //foreach (Element elem in instances) //{ // bool b_Type = Util.GetFamilyPartType(elem, PartType.Tee); // if (b_Type == false) continue; // // FamilyInstance Teefam = elem as FamilyInstance; // LocationPoint locpt = Teefam.Location as LocationPoint; // // if (locpt.Point.IsAlmostEqualTo(InterPt, Unit.MMToFeet(0.01))) // { // //Util.Pyosi(doc, locpt.Point, 1); // CrossTee = elem as FamilyInstance; // break; // } //} //if (CrossTee != null) //{ // Connector ColumnCon = null; // // Connector PipeCon = null; // Connector BranchTeeCon = GetTeeBranchConnector(CrossTee, MainVec, ReverseVec); // Connector NextOtherCon = null; // //Util.Pyosi(doc, BranchTeeCon.Origin, 1); // int cnt = 0; // while (true) // { // Connector NextCon = Util.GetNextElementConnector(BranchTeeCon); // // //선택한 엘보 패밀리가 나올 때 까지 반복 // if(!(NextCon.Owner is FamilyInstance)) // { // NextOtherCon = Util.GetOtherConnector(NextCon); // BranchTeeCon = NextOtherCon; // continue; // } // // if (Util.GetFamilyPartType(NextCon,PartType.Elbow) == true) // { // FamilyInstance family = NextCon.Owner as FamilyInstance; // // if (family.Id == ElbowFamily.Id) // { // //엘보에 붙어있는 파이프 커넥터 구하기 // ColumnCon = BranchTeeCon; // Connector ElbowCon = NextCon; // Connector ElbowOtherCon = Util.GetOtherConnector(ElbowCon); // PipeCon = Util.GetNextElementConnector(ElbowOtherCon); // // //Util.Pyosi(doc, NextCon.Origin,1); // //Util.Pyosi(doc, ElbowOtherCon.Origin,1); // break; // } // } // // NextOtherCon = Util.GetOtherConnector(NextCon); // BranchTeeCon = NextOtherCon; // // cnt++; // if (cnt > 3000) break; // }//while end // // Connector lastSpCon = null, lastEpCon = null; // using (Transaction trans = new Transaction(doc)) // { // trans.Start("1"); // //doc.Regenerate(); // List DrawPipeLst = Util.CreatePipe(uiapp, doc, BranchPtLst, Spkr_Func.MainSystemTypeId, Spkr_Func.MainPipeTypeId, Spkr_Func.MainLevelId); // // List ElemIdLst = Spkr_Func.ConnectHead2pipe(lst_objSprinkler, DrawPipeLst, headDiaLst); // // //Util.Pyosi(doc, ElbowPipeCon.Origin, 0); // doc.Delete(ElbowFamily.Id); // // Pipe LastPipe = doc.GetElement(ElemIdLst.Last()) as Pipe; // //작도된 파이프 중 메인에 가까운 파이프 끝점 // Util.GetStartEndConnector(LastPipe, ref lastSpCon, ref lastEpCon); // // //파이프 관경이 다를경우 레듀셔일 수 있어 다음객체 찾고 레듀셔 지움 // if (!(PipeCon.Owner is Pipe)) // { // Connector OtherCon = Util.GetOtherConnector(PipeCon); // PipeCon = Util.GetNextElementConnector(OtherCon); // doc.Delete(OtherCon.Owner.Id); // } // // if (!(ColumnCon.Owner is Pipe)) // { // Connector OtherCon = Util.GetOtherConnector(ColumnCon); // ColumnCon = Util.GetNextElementConnector(OtherCon); // doc.Delete(OtherCon.Owner.Id); // } // // // XYZ MoveElbowPt = Util.Polar(PipeCon.Origin, // lastEpCon.Origin, lastSpCon.Origin, PipeCon.Origin.DistanceTo(lastEpCon.Origin)); // //엘보에 붙어있던 파이프 위치 조정 // PipeCon.Origin = MoveElbowPt; // // Connector ColumnOtherCon = Util.GetOtherConnector(ColumnCon); // XYZ MoveColumnPt = Util.Polar(ColumnCon.Origin, // ColumnOtherCon.Origin, ColumnCon.Origin, ColumnCon.Origin.DistanceTo(lastEpCon.Origin)); // //Tee 기둥 위치 조정 // ColumnCon.Origin = MoveColumnPt; // //Tee 작도 // FamilyInstance familyTee = creDoc.NewTeeFitting(lastEpCon, PipeCon, ColumnCon); // // if(Math.Abs(lastEpCon.Origin.Z - PipeCon.Origin.Z) > Unit.MMToFeet(0.1)) // { // MessageBox.Show("양쪽의 가지관 높이가 다릅니다."); // return Result.Failed; // } // //왼쪽 오른쪽 관경이 다를 경우 레듀셔와 Tee 사이 간격 띄우기 // if (!(Math.Abs(lastEpCon.Radius - PipeCon.Radius) < Unit.MMToFeet(0.01))) // { // Spkr_Func.CreatePipeBetweenTeeAndReducer(familyTee, 100); // } // // trans.Commit(); // } ////} break; } }//while end } catch (Exception e) { using (Transaction trans = new Transaction(doc)) { trans.Start("delete"); doc.Regenerate(); if (RemoveElemIdLst.Count() > 0) doc.Delete(RemoveElemIdLst); trans.Commit(); } //MessageBox.Show("" + e); } return Result.Succeeded; } //기준 커넥터에서 FlowVec 방향 커넥터 구하기(Tee 또는 Cross에서 사용) public Connector GetTeeBranchConnector(FamilyInstance familyTee, XYZ FlowVec, XYZ ReverseVec) { Connector resCon = null; ConnectorSet ConSet = null; FamilyInstance family = null; Pipe pipe = null; List TeeConLst = Util.GetElementConnectors(familyTee); foreach (Connector TeeCon in TeeConLst) { if (TeeCon.IsConnected == true) { family = TeeCon.Owner as FamilyInstance; ConSet = family.MEPModel.ConnectorManager.Connectors; foreach (Connector con in ConSet) { if (TeeCon.Origin.IsAlmostEqualTo(con.Origin, Unit.MMToFeet(0.01))) continue; XYZ CurVec = (con.Origin - TeeCon.Origin).Normalize(); if (!(CurVec.IsAlmostEqualTo(FlowVec, Unit.MMToFeet(0.01)) || CurVec.IsAlmostEqualTo(ReverseVec, Unit.MMToFeet(0.01)))) resCon = con; } } } return resCon; } //메인과 가지관 엘보 작도 public void MainConnectElbow(Element MainPipeElem, Element BranchElem) { Connector SpCon = null, EpCon = null; Pipe NewPipe = null; Util.GetStartEndConnector(BranchElem as Pipe, ref SpCon, ref EpCon); NewPipe = Spkr_Func.CreatePipeFromNearPt(MainPipeElem, EpCon); //파이프 엘보 관경 맞추고 연결 Connector NewSpCon = null, NewEpCon = null; Util.GetStartEndConnector(NewPipe, ref NewSpCon, ref NewEpCon); NewSpCon.Radius = EpCon.Radius; Util.ElbowFitting(doc, EpCon, NewSpCon); //메인관에 T연결 Connector pipeSpCon = null, pipeEpCon = null; bool b_Cons = Util.GetStartEndConnector(NewPipe, ref pipeSpCon, ref pipeEpCon); Line DirectLine = ((MainPipeElem as Pipe).Location as LocationCurve).Curve as Line; XYZ DivPt = Util.GetPointOnLine(DirectLine, pipeEpCon.Origin); ElementId divID = PlumbingUtils.BreakCurve(doc, MainPipeElem.Id, DivPt); Connector MainCon1 = null, MainCon2 = null; List MainCon1Lst = Util.GetElementConnectors(doc.GetElement(divID)); List MainCon2Lst = Util.GetElementConnectors(MainPipeElem); foreach (Connector con1 in MainCon1Lst) { foreach (Connector con2 in MainCon2Lst) { if (con1.Origin.IsAlmostEqualTo(con2.Origin, Unit.MMToFeet(0.01))) { MainCon1 = con1; MainCon2 = con2; } } } Util.CreateTee(creDoc, MainCon1, MainCon2, pipeEpCon); } public class SelectionMainPipe : 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 SelectionFilter : ISelectionFilter { public bool AllowElement(Element element) { if (element.Category == null) return false; if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_Sprinklers || element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves || element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting) { return true; } return false; } public bool AllowReference(Reference refer, XYZ point) { return false; } } } }