-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dimension Walls In Plan.dyn
234 lines (234 loc) · 59.5 KB
/
Dimension Walls In Plan.dyn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
{
"Uuid": "a01201e9-a1a0-4466-ab04-f9789e94ade1",
"IsCustomNode": false,
"Description": null,
"Name": "Dimension Walls In Plan",
"ElementResolver": {
"ResolutionMap": {}
},
"Inputs": [],
"Outputs": [],
"Nodes": [
{
"ConcreteType": "CoreNodeModels.Input.BoolSelector, CoreNodeModels",
"NodeType": "BooleanInputNode",
"InputValue": false,
"Id": "ea4ea2090366416c9b6745d4d181eebb",
"Inputs": [],
"Outputs": [
{
"Id": "a0b66b724e764136bb41244cda3b06c9",
"Name": "",
"Description": "Boolean",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Replication": "Disabled",
"Description": "Selection between a true and false."
},
{
"ConcreteType": "PythonNodeModels.PythonNode, PythonNodeModels",
"NodeType": "PythonScriptNode",
"Code": "#thanks to Ben Robinson\r\n#alternatitvely you can load the XAML file using PresentationFramework in presentationframework but with some limitations\r\n\r\nimport clr\r\nimport sys\r\npyt_path = r'C:\\Program Files (x86)\\IronPython 2.7\\Lib'\r\nsys.path.append(pyt_path)\r\n\r\n#############-------------\\-------------##############\r\n\r\n ### UI additional references ###\r\n \r\nclr.AddReference(\"System.Windows.Forms\")\r\nclr.AddReference(\"System.Drawing\")\r\n\r\nfrom System.Windows.Forms import Application, Form, FormWindowState, Screen, Label, PictureBox, PictureBoxSizeMode, AnchorStyles, BorderStyle, ComboBox, ComboBoxStyle, FormBorderStyle, CheckBox, TextBox, TextBoxBase\r\nfrom System.Windows.Forms import Button, LinkLabel, Panel, Button\r\nfrom System.Drawing import Icon, Color, Font, Point, Size#, Image\r\n\r\n#system location C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\r\nimport System.IO\r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Define some variables ###\r\n\r\n#these variables are static through the 2 windows\r\nbitmapImage = System.Drawing.Bitmap(\"C:\\Me\\Dynamo\\WPF in Dynamo\\\\\" + \"dyna-sco-logo.png\") #titlebar logo as bmp\r\ntitleIcon = Icon.FromHandle(bitmapImage.GetHicon()) #titlebar logo as icon\r\ntitleText = \"Dimensioning\" #text that appears in the GUI titlebar\r\nbtnHeight = 40 #declared here as used for btn locations\r\nbtnWidth = 120\r\nspacing = 20 #spacing size for GUI elements to form a consistent border\r\nfontMessage = Font(\"Helvetica \", 9)\r\nfontCK = Font(\"Helvetica \", 8) #set Checkbox Font\r\nwinSize = Size(1000,700) #consistant window size\r\n\r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Global defs ###\r\n \r\ndef button(txt, loc, clc):\r\n btn = Button()\r\n #btnCancel.Parent = self\r\n btn.Text = txt\r\n btn.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right)\r\n btn.Location = loc\r\n btn.Click += clc\r\n btn.Height = btnHeight\r\n btn.Width = btnWidth\r\n btn.BackColor = Color.FromArgb(220, 220, 220)\r\n return btn\r\n\r\ndef logo(uiW, uiH):\r\n logo = PictureBox()\r\n bitmapImage = System.Drawing.Bitmap(\"C:\\Me\\Dynamo\\WPF in Dynamo\\\\\" + \"dyna-sco-logo-text.png\") \r\n logo.Image = bitmapImage\r\n ratio = float(logo.Height)/ float(logo.Width) #needs to be a float as int will round to the nearest whole number\r\n logo.Size = Size(220, 130*ratio) #fixed for consistancy\r\n logo.Location = Point(spacing, (uiH - logo.Height)-spacing)\r\n logo.SizeMode = PictureBoxSizeMode.Zoom # zooms the image to fit the extent\r\n logo.Anchor = (AnchorStyles.Bottom | AnchorStyles.Left) #anchor styles lock elements to a given corner of the GUI if you allow users change size\r\n return logo\r\n\r\n\r\n##########################-------------\\-------------##########################\r\n\r\n ### Create a Class to define the first window ###\r\n \r\n# create a instance of the form class called dimsionInputs.\r\n#In Winforms, any window or a dialog is a Form.# \r\n\r\nclass dimsionInputs(Form): \r\n\r\n def __init__(self): #the __init__ method inside a class is its constructor\r\n\r\n self.Text = titleText \r\n self.Icon = titleIcon\r\n self.BackColor = Color.FromArgb(255, 255, 255) \r\n self.WindowState = FormWindowState.Normal # set maximised minimised or normal size GUI\r\n self.CenterToScreen() #centres GUI to the middle of your screen \r\n self.BringToFront() #brings the GUI to the front of all open windows\r\n self.Topmost = True #true to display the GUI infront of any other active forms\r\n self.Size = winSize #small enough to fit on most screens\r\n uiWidth = self.DisplayRectangle.Width #get the size of the form to use to scale form elements\r\n uiHeight = self.DisplayRectangle.Height\r\n stHeight = uiHeight - 400 #the height at which the check & text boxes will start\r\n htSpacing = 50 #a standard spacing vertical gap betwen check & text boxes \r\n self.FormBorderStyle = FormBorderStyle.FixedDialog # fixed dialog stops the user from adjusting the form size. Recomended disabling this when testing to see if elements are in the wrong place.#\r\n \r\n ### Set Default Values ###\r\n \r\n# self.dropDownOutput = 'pick one'\r\n \r\n self.txtBoxOffOutput = '500' #offset of dimension from wall\r\n self.txtBoxCoordOutput = 'Internal' #name of coordinate system to be used\r\n self.ckBoxESOutput = False #External Side?\r\n self.ckBoxLWOutput = False #Linked Walls?\r\n self.ckBoxAWOutput = False #All Walls?\r\n self.ckBoxMDOutput = False #Multiple dims per wall?\r\n self.messText = 'test'\r\n self.runNextOutput = False #how we decide if we want the next window to fire#\r\n self.Controls.Add(logo(uiWidth, uiHeight)) #add logo\r\n \r\n#############-------------\\-------------#############\r\n\r\n ### Create Main Window Text ###\r\n \r\n userMessage = Label() #label displays texts\r\n font = fontMessage\r\n userMessage.Text = 'Automatic Dimensions for Linked or Project Walls \\n\\nPlease make sure your walls are not inside out \\nButt joints will give extraneous results'\r\n userMessage.Font = font\r\n userMessage.Location = Point(spacing, spacing) #all location require a point object from system.Drawing to set the location.\r\n userMessage.Size = Size(uiWidth-(spacing*2),(uiHeight/4)) #size the control with the width of the GUI to ensure it scales with different screen\r\n self.Controls.Add(userMessage) #this adds control element to the GUI\r\n\r\n#############-------------\\-------------#############\r\n\r\n #combox drop down\r\n# cBox = ComboBox() #dropdown control form\r\n# cBox.Location = Point(spacing,uiHeight/3) \r\n# cBox.Width = uiWidth -(spacing*2)\r\n# cBox.Items.AddRange(tuple[(1,2,3,])) # Adds an array of items to the list of items for a ComboBox.\r\n# cBox.DropDownStyle = ComboBoxStyle.DropDownList #setting to dropdown list prevents users from being able to add aditional text values\r\n# cBox.SelectedIndexChanged += self.dropDownOutput #.Click+= registers the press of the button to register the event handler and determine what action takes place when button clicked\r\n# self.Controls.Add(cBox) \r\n\r\n#############-------------\\-------------#############\r\n\r\n ### CHECKBOXES ##\r\n \r\n #checkbox Linked Walls \r\n ckBoxLW = CheckBox()\r\n ckBoxLW.Name=\"Linked Walls\" \r\n ckBoxLW.Text=\"Linked Walls?\"\r\n ckBoxLW.Location = Point(spacing,stHeight+htSpacing) \r\n ckBoxLW.Width = uiWidth -(spacing*2)\r\n ckBoxLW.Font = fontCK\r\n ckBoxLW.Height = 40\r\n ckBoxLW.CheckStateChanged += self.ckBoxLWChecked\r\n\r\n \r\n #checkbox All Walls\r\n ckBoxAW = CheckBox()\r\n ckBoxAW.Name=\"All Walls\" \r\n ckBoxAW.Text=\"All Walls?\"\r\n ckBoxAW.Location = Point(spacing,(stHeight+htSpacing*2)) \r\n ckBoxAW.Width = uiWidth -(spacing*2)\r\n ckBoxAW.Height = 40\r\n ckBoxAW.Font = fontCK\r\n ckBoxAW.CheckStateChanged += self.ckBoxAWChecked\r\n \r\n #checkbox External Side\r\n ckBoxES = CheckBox()\r\n ckBoxES.Name=\"External Side\" \r\n ckBoxES.Text=\"External Side? (or internal side)\"\r\n ckBoxES.Location = Point(spacing,stHeight) \r\n ckBoxES.Width = uiWidth -(spacing*2)\r\n ckBoxES.Font = fontCK\r\n ckBoxES.Height = 40 \r\n ckBoxES.CheckStateChanged += self.ckBoxESChecked\r\n \r\n #checkbox MultiDims\r\n ckBoxMD = CheckBox()\r\n ckBoxMD.Name=\"Multi-Dims\" \r\n ckBoxMD.Text=\"Multi-Dims for each wall (for brick checking)\"\r\n ckBoxMD.Location = Point(spacing,(stHeight+htSpacing*3)) \r\n ckBoxMD.Width = uiWidth -(spacing*2)\r\n ckBoxMD.Height = 40\r\n ckBoxMD.Font = fontCK\r\n ckBoxMD.CheckStateChanged += self.ckBoxMDChecked\r\n \r\n #add to Window\r\n self.Controls.Add(ckBoxES)\r\n self.Controls.Add(ckBoxLW)\r\n self.Controls.Add(ckBoxAW) \r\n self.Controls.Add(ckBoxMD) \r\n\r\n#############-------------\\-------------#############\r\n\r\n ### TEXTBOXES ##\r\n \r\n #TextBox Coordinate System \r\n textBoxCoord = TextBox()\r\n textBoxCoord.Width = 300\r\n textBoxCoord.Text=\"Internal\"\r\n textBoxCoord.Font = fontCK\r\n textBoxCoord.Location = Point(spacing + 400 ,(stHeight+htSpacing*4))\r\n textBoxCoord.TextChanged += self.txtBoxCoordChanged\r\n \r\n #TextBox Coordinate System - Label\r\n textBoxCoordLabel = Label() #label displays texts\r\n textBoxCoordLabel.Text = \"Coordinate System Name\"\r\n textBoxCoordLabel.Width = 400\r\n textBoxCoordLabel.Font = fontCK\r\n textBoxCoordLabel.Location = Point(spacing,(stHeight+htSpacing*4))\r\n textBoxCoordLabel.Height = 50\r\n \r\n #add to Window\r\n self.Controls.Add(textBoxCoordLabel) \r\n self.Controls.Add(textBoxCoord)\r\n \r\n \r\n \r\n #TextBox Offset \r\n textBoxOffset = TextBox()\r\n textBoxOffset.Location = Point(spacing + 400,(stHeight+htSpacing*5)) \r\n textBoxOffset.Width = 300\r\n textBoxOffset.Text= \"500\"\r\n textBoxOffset.Name=\"Offset Distance\" \r\n textBoxOffset.Font = fontCK\r\n textBoxOffset.TextChanged += self.txtBoxOffChanged\r\n\r\n \r\n #TextBox Offset - Label\r\n textBoxOffsetLabel = Label() #label displays texts\r\n textBoxOffsetLabel.Text = \"Offset Distance\"\r\n textBoxOffsetLabel.Width = 200\r\n textBoxOffsetLabel.Font = fontCK\r\n textBoxOffsetLabel.Height = 40\r\n textBoxOffsetLabel.Location = Point(spacing,(stHeight+htSpacing*5))\r\n #this is how you would do a margin\r\n #textBoxOffsetLabel.Margin = Padding(712,418,0,0) \r\n \r\n #add to Window\r\n self.Controls.Add(textBoxOffsetLabel) \r\n self.Controls.Add(textBoxOffset)\r\n \r\n#############-------------\\-------------############# \r\n\r\n ### Buttons ## \r\n\r\n #Create Ok Button\r\n btnOkClick = self.okButtonPressed #register click by user\r\n btnOkLoc = Point(uiWidth - ((btnWidth * 2) + spacing + 30), uiHeight - (btnHeight + spacing))\r\n btnOk = button('OK', btnOkLoc, btnOkClick) \r\n \r\n #Create Cancel Button\r\n btnCnclClick = self.CnlButtonPressed #register click by user\r\n btnCnclLoc = Point(uiWidth - (btnHeight + spacing + 90), uiHeight - (btnHeight + spacing ))\r\n btnCancel = button('Cancel', btnCnclLoc, btnCnclClick)\r\n \r\n #add to Window\r\n self.Controls.Add(btnOk)\r\n self.Controls.Add(btnCancel) \r\n \r\n#############-------------\\-------------#############\r\n\r\n ### Return Info From User ##\r\n\r\n#these defs are the mechanism by which we assess the info from the user\r\n#self is the instance of the GUI form. Sender is the control/widget. args is the argument/event provided from the control \r\n\r\n ###dropDown ####\r\n# def dropDownOutput(self, sender, args):\r\n# self.dropDownOutput = sender.SelectedItem #output the selected item.\r\n\r\n ### checkBoxes ### \r\n def ckBoxESChecked(self, sender, args):\r\n if sender.Checked:\r\n self.ckBoxESOutput = True\r\n #otherwise indeterminate states give erroneous results\r\n else:\r\n self.ckBoxESOutput = False \r\n \r\n def ckBoxLWChecked(self, sender, args):\r\n if sender.Checked:\r\n self.ckBoxLWOutput = True\r\n else:\r\n self.ckBoxLWOutput = False\r\n \r\n def ckBoxAWChecked(self, sender, args):\r\n if sender.Checked:\r\n self.ckBoxAWOutput = True\r\n else:\r\n self.ckBoxAWOutput = False\r\n \r\n def ckBoxMDChecked(self, sender, args):\r\n if sender.Checked:\r\n self.ckBoxMDOutput = True\r\n else:\r\n self.ckBoxMDOutput = False\r\n \r\n \r\n ### textBoxes ### \r\n def txtBoxOffChanged(self, sender, args): \r\n self.txtBoxOffOutput = sender.Text\r\n \r\n \r\n def txtBoxCoordChanged(self, sender, args):\r\n self.txtBoxCoordOutput = sender.Text \r\n\r\n ### buttons ###\r\n def okButtonPressed(self, sender, args):\r\n numErrorProvider = System.Windows.Forms.ErrorProvider()\r\n try:\r\n int(self.txtBoxOffOutput)\r\n self.Close() #trigger to close the GUI when button is pressed\r\n self.runNextOutput = True #if the ok button is pressed set runNextOutput as True\r\n except ValueError: \r\n numErrorProvider.SetError(sender, 'Offset must be a number')\r\n def CnlButtonPressed(self, sender, args):\r\n self.Close()\r\n self.runNextOutput = False #if the cancel button is pressed set runNextOutput as False \r\n\r\n \r\n##########################-------------\\-------------##########################\r\n\r\n ### And Run ##\r\n\r\ndimForm = dimsionInputs() \r\n\r\nApplication.Run(dimForm)\r\n\r\nOUT = dimForm.runNextOutput, dimForm.ckBoxLWOutput, dimForm.ckBoxAWOutput, dimForm.ckBoxESOutput, dimForm.ckBoxMDOutput, dimForm.txtBoxCoordOutput, dimForm.txtBoxOffOutput,",
"VariableInputPorts": true,
"Id": "aab1c51701d84489a86dbbb44a8a919a",
"Inputs": [
{
"Id": "e76381f7d18b41d78620a9cb93c838ab",
"Name": "IN[0]",
"Description": "Input #0",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Outputs": [
{
"Id": "1ced077741d24e159afd44adc3c66516",
"Name": "OUT",
"Description": "Result of the python script",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Replication": "Disabled",
"Description": "Runs an embedded IronPython script."
},
{
"ConcreteType": "PythonNodeModels.PythonNode, PythonNodeModels",
"NodeType": "PythonScriptNode",
"Code": "#thanks for all the help everyone\r\nimport clr\r\n\r\n# Import RevitAPI\r\nclr.AddReference(\"RevitAPI\")\r\nimport Autodesk\r\nfrom Autodesk.Revit.DB import *\r\nimport System\r\n\r\nclr.AddReference(\"ProtoGeometry\")\r\nfrom Autodesk.DesignScript import Geometry as geom\r\n\r\n# Import Element wrapper extension methods\r\nclr.AddReference(\"RevitNodes\")\r\nimport Revit\r\nfrom Autodesk.Revit.DB import *\r\n\r\n# Import ToProtoType, ToRevitType geometry conversion extension methods\r\nclr.ImportExtensions(Revit.GeometryConversion)\r\n\r\nclr.AddReference(\"RevitAPIUI\")\r\nfrom Autodesk.Revit.UI.Selection import ObjectType\r\nfrom Autodesk.Revit.UI import * #TaskDialog#\r\n#from Autodesk.Revit.UI import TaskDialogCommonButtons\r\n#from Autodesk.Revit.UI import TaskDialogResult\r\n\r\nclr.AddReference(\"ProtoGeometry\")\r\nfrom Autodesk.DesignScript import Geometry as geom\r\n\r\n#for our selection box\r\nfrom Autodesk.Revit.UI.Selection import *\r\n\r\n# Import DocumentManager and TransactionManager #\r\nclr.AddReference(\"RevitServices\")\r\nimport RevitServices\r\nfrom RevitServices.Persistence import DocumentManager\r\nfrom RevitServices.Transactions import TransactionManager\r\n\r\ndoc = DocumentManager.Instance.CurrentDBDocument\r\nuidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument\r\n\r\n\r\ndef isParallel(v1, v2):\r\n #it needs two vectors\r\n return v1.CrossProduct(v2).IsAlmostEqualTo(XYZ(0, 0, 0))\r\n\r\ndef isAlmostEqualTo(v1, v2):\r\n return v1.IsAlmostEqualTo(v2)\r\n\r\ndef isPerpendicular(v1, v2):\r\n if v1.DotProduct(v2)== 0:\r\n return True\r\n else:\r\n return False\r\n\r\ndef tolist(obj1):\r\n\tif hasattr(obj1,\"__iter__\"): return obj1\r\n\telse: return [obj1]\r\n\r\ndef CurveToVector(crv):\r\n\tvec = geom.Vector.ByTwoPoints(crv.StartPoint,crv.EndPoint)\r\n\treturn vec\r\n\r\n#set the wall orientation, depending on whether exterior or interior is selected\r\ndef wallNormal(wall, extOrint):\r\n if extOrint:\r\n wallNormal = wall.Orientation.ToVector()\r\n else:\r\n wallNormal = wall.Orientation.Negate().ToVector()\r\n return wallNormal\r\n\r\n#so to compensate for different shared position heights, we need the Internal Project Point, even if it's not current!\r\n#otherwise our cutting line will not have the correct Z value\r\ndef projectPos(locationName):\r\n projectLocs = doc.ProjectLocations\r\n for loc in projectLocs:\r\n if loc.Name == locName:\r\n pos = XYZ(0,0,0)\r\n locPosition = loc.GetProjectPosition(pos).Elevation\r\n return locPosition\r\n#this takes the wall location line, shifts it up the to the view cut plane\r\n#and moves it out to the external edge of the wall\r\ndef locToCutCrv(wall, wallNormal, lineEndExtend, locPos):\r\n wallLn = wall.Location.Curve\r\n #we're using Design Script for the geometry move, so Metric units\r\n wallCrv = wallLn.ToProtoType()\r\n locPositionMM = UnitUtils.ConvertFromInternalUnits(locPos, DisplayUnitType.DUT_MILLIMETERS)\t\t\r\n #take the view's level height above ground level relative to the project origin & convert to MM\r\n zOfMM = UnitUtils.ConvertFromInternalUnits(doc.ActiveView.GenLevel.ProjectElevation, DisplayUnitType.DUT_MILLIMETERS)\r\n #get the wall location line's height... this is where our clash line starts from\r\n #we need to compensate for the Internal Project Point's shift\r\n wallCrvZ = wallCrv.StartPoint.Z + locPositionMM\r\n #get the cut plane offset of the view\r\n #the CutPlane enumeration is ia property of PBP?\r\n cPlaneH = doc.ActiveView.GetViewRange().GetOffset(PlanViewPlane.CutPlane)\r\n cPlaneHiMM = UnitUtils.ConvertFromInternalUnits(cPlaneH, DisplayUnitType.DUT_MILLIMETERS)\t\r\n wallCrv = geom.Geometry.Translate(wallCrv, geom.Vector.ByCoordinates(0,0, zOfMM + cPlaneHiMM + locPositionMM - wallCrvZ))\r\n wallwidthMM = UnitUtils.ConvertFromInternalUnits(wall.Width, DisplayUnitType.DUT_MILLIMETERS)\r\n wallCrv = geom.Geometry.Translate(wallCrv, wallNormal, (wallwidthMM/2))\t\r\n #get wall curve info\r\n wallvec = CurveToVector(wallCrv)\r\n wallorig = geom.Curve.PointAtParameter(wallCrv,0.5)\r\n walldir1 = geom.Vector.ByTwoPoints(wallorig, wallCrv.StartPoint)\r\n walldir2 = geom.Vector.ByTwoPoints(wallorig, wallCrv.EndPoint)\r\n #move points\r\n ptMvSt = geom.Geometry.Translate(wallCrv.StartPoint, walldir1, lineEndExtend)\r\n ptMvEnd = geom.Geometry.Translate(wallCrv.EndPoint, walldir2, lineEndExtend)\r\n #create new line based on extended points\r\n #this is not a model line! that requires another method\r\n lineAtExternalEdgeAtCutPlaneHeight = geom.Line.ByStartPointEndPoint(ptMvSt, ptMvEnd).ToRevitType()\r\n return lineAtExternalEdgeAtCutPlaneHeight\r\n\r\n#go get those references!\r\n#we also noeed to deal with linked references thanks to maciek.glowka lubim.co/\r\ndef parseLinkedReference(doc, linkedRef):\r\n reps = linkedRef.ConvertToStableRepresentation(doc).split(':') \r\n res = ''\r\n first=True \r\n \r\n for i, s in enumerate(reps):\r\n t = s\r\n if \"RVTLINK\" in s:\r\n if(i<len(reps)-1):\r\n if reps[i+1]==\"0\":\r\n t = \"RVTLINK\"\r\n else:\r\n t = \"0:RVTLINK\"\r\n else:\r\n t = \"0:RVTLINK\"\r\n if not first:\r\n res = res + \":\" + t\r\n else:\r\n res = t\r\n first = False\r\n \r\n ref = Reference.ParseFromStableRepresentation(doc,res)\r\n \r\n return ref\r\n\r\n\r\ndef addInListArray(locationsList, origList, lnkWalls, linkInstance, document):\r\n locTemp = []\r\n sub = ReferenceArray()\r\n for eL, e in zip(locationsList, origList):\r\n if eL not in locTemp:\r\n locTemp.append(eL)\r\n if linkedWalls:\r\n linkedReference = e.Reference.CreateLinkReference(linkInstance) \r\n ref = parseLinkedReference(document,linkedReference)\r\n sub.Append(ref) \r\n else:\r\n sub.Append(e.Reference)\r\n return sub\r\n\r\n#sadly the collector doesn't work for links so we need to use more brute force methods\r\n#create a virtual solid and intersect with transform!\r\ndef linkedWallsInActiveView(docLnk,refElemLink, cropSh, solidBaseXYZ, solidTopHt, targetWalls):\r\n if docLinked != None and doc.ActiveView.CropBoxVisible:\r\n #Creation of the intersecting solid box for the link (in this case almost in origin)\r\n linkInst = doc.GetElement(refElemLink.ElementId)\r\n virtualSolid = GeometryCreationUtilities.CreateExtrusionGeometry(cropSh, solidBaseXYZ, solidTopHt)\r\n virtualLinkSolid = SolidUtils.CreateTransformed(virtualSolid, linkInst.GetTotalTransform().Inverse)\r\n solidIntersecFil = Autodesk.Revit.DB.ElementIntersectsSolidFilter(virtualLinkSolid)\r\n instanceElementsInViewRvL = FilteredElementCollector(docLinked).WhereElementIsNotElementType().WherePasses(solidIntersecFil)\r\n\r\n else:\r\n #so we want to get all walls in the extent of the view if the view is not cropped.\r\n #we don't want to use the crop region, because that might have been left at some tiny\r\n #part of the screen.\r\n #so we will get all the walls in the model, get the max and min of their bounding box\r\n #and create a new bounding box which spans all of them\r\n #we can then create a solid from it using the level offset and cutplane, and run an intersect on that\r\n #Bounding boxes of walls in link \r\n allWallsInLnkNDocBB = [] \r\n for lnkWall in targetWalls:\r\n lnkWallBB = lnkWall.get_BoundingBox(None)\r\n allWallsInLnkNDocBB.append(lnkWallBB) \r\n #Bounding boxes of walls in doc\r\n #seems like it will be handy for when we don't want links\r\n #for wallInDoc in wallsinDoc:\r\n # wallBB = wallInDoc.get_BoundingBox(None)\r\n # allWallsInLnkNDocBB.append(wallBB)\r\n #get bb max and mins\r\n bBMaxX, bBMaxY, bBMinX, bBMinY = [],[],[],[] \r\n for wallBB in allWallsInLnkNDocBB:\r\n bBMinX.append(wallBB.Min.X)\r\n bBMinY.append(wallBB.Min.Y)\r\n bBMaxX.append(wallBB.Max.X)\r\n bBMaxY.append(wallBB.Max.Y)\r\n #now input the max and min values \r\n pt0 = XYZ(min(bBMinX), min(bBMinY), solidBaseHtZ)\r\n pt1 = XYZ(max(bBMaxX), min(bBMinY), solidBaseHtZ)\r\n pt2 = XYZ(max(bBMaxX), max(bBMaxY), solidBaseHtZ)\r\n pt3 = XYZ(min(bBMinX), max(bBMaxY), solidBaseHtZ)\r\n #edges in BBox coords\r\n edge0 = Line.CreateBound(pt0, pt1)\r\n edge1 = Line.CreateBound(pt1, pt2)\r\n edge2 = Line.CreateBound(pt2, pt3)\r\n edge3 = Line.CreateBound(pt3, pt0)\r\n #create loop, still in BBox coords\r\n edges =list()\r\n edges.Add(edge0);\r\n edges.Add(edge1);\r\n edges.Add(edge2);\r\n edges.Add(edge3);\r\n baseLoop = CurveLoop.Create(edges)\r\n loopList = list()\r\n loopList.Add(baseLoop)\r\n linkInst = doc.GetElement(refElemLinked.ElementId)\r\n VirtualSolid = GeometryCreationUtilities.CreateExtrusionGeometry(loopList, solidBaseXYZ, 5)\r\n VirtualLinkSolid = SolidUtils.CreateTransformed(VirtualSolid, linkInst.GetTotalTransform().Inverse)\r\n solidIntersecFil = Autodesk.Revit.DB.ElementIntersectsSolidFilter(VirtualLinkSolid)\r\n #we used all the walls to make our filter, but for this, we are only returning linked walls\r\n fec=ElementCategoryFilter(BuiltInCategory.OST_Walls)\r\n instanceElementsInViewRvL = FilteredElementCollector(docLinked).WherePasses(fec).WhereElementIsNotElementType().WherePasses(solidIntersecFil)\r\n return instanceElementsInViewRvL\r\n\r\nclass selFilt(ISelectionFilter):\r\n #\"__init__\" is a reseved method in python classes. It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.\r\n #it's almost like the self is implied? it has to be there but has no variable, we can't use the allow element function without a separate init, we then must have an equation to keep the code format\r\n\tdef __init__(self, element):\r\n\t\te = element\r\n\tdef AllowElement(self, e):\r\n\t\tif e.ToString() == 'Autodesk.Revit.DB.Wall':\r\n\t\t\treturn True\r\n\t\telse:\r\n\t\t\treturn False\r\n\tdef AllowReference(self, ref, point):\r\n\t\treturn true\r\n\r\n####and we are off ####\r\n\r\n#let's get some settings from the user\r\n#can't add sophisticated inputs like text or numbers\r\n#a series of these would take more time than just dimensioning it\r\n#refer to WPF\r\n#title = 'SettingsInput'\r\n#td = TaskDialog(title)\r\n#td.MainInstruction = 'Please check these settings'\r\n#td.CommonButtons = TaskDialogCommonButtons.Ok|TaskDialogCommonButtons.Cancel\r\n#can't have verification and extra checkbox\r\n#td.VerificationText = 'This is \\'VerificationText'\r\n#td.AddCommandLink(TaskDialogCommandLinkId.CommandLink1,\r\n# \"Use Simple Insertion Point\",\r\n# \"This option works for free-floating items\");\r\n#td.ExtraCheckBoxText = 'Linked Walls?'\r\n#td.AllowCancellation = True\r\n#res = td.Show()\r\n#td.WasExtraCheckBoxChecked()\r\nrun = IN[0][0]\r\noption = IN[0][1]\r\nextOrInt = IN[0][2]\r\nmultiDim = IN[0][3]\r\nlocName = IN[0][4]\r\noffDist = float(IN[0][5]) #text box input\r\n\r\nif option == 2 or option == 3 or option == 6:\r\n linkedWalls = True\r\nelse:\r\n linkedWalls = False\r\n#if the wall is exterior we need to extend the intersect line\r\n#beyond the exterior face to pick up the intersecting walls\r\n#if the wall is interior, we don't want to extend as far\r\nif extOrInt:\r\n intersectLineEndExtend = 500\r\nelse:\r\n intersectLineEndExtend = 0\r\n\r\n\r\n#view info for generating virtual solid for linked walls\r\n#if GenLevel fails it means we're not in a floor plan, so we run\r\n#a fail dialogue\r\ntry:\r\n solidBaseHtZ = doc.ActiveView.GenLevel.ProjectElevation\r\n solidBaseXYZ = XYZ(0,0,1)\r\n if solidBaseXYZ.Z < 1:\r\n solidBaseXYZ == XYZ(0,0,1)\r\n #get the cut plane offset of the view\r\n solidTopHt= doc.ActiveView.GetViewRange().GetOffset(PlanViewPlane.CutPlane)\r\n cropShape = doc.ActiveView.GetCropRegionShapeManager().GetCropShape()\r\nexcept:\r\n failDialogue = TaskDialog('Fail')\r\n failText = 'You do not appear to be in a floor plan... We need a floor plan for this to work!' \r\n failDialogue.MainInstruction = failText\r\n failDialogue.Show()\r\n OUT = failText\r\n\r\n#See if there's anything selected\r\nselectedIds = uidoc.Selection.GetElementIds()\r\n\r\ntargetWalls, pickSel, refElemsLinked = [], [], []\r\nrefElemLinked = Element\r\n\r\n#we are wanting document elements unless linked walls is True \r\nobt = ObjectType.Element\r\n\r\nif linkedWalls:\r\n obt = ObjectType.LinkedElement\r\n\r\n#if no selection and not a link\r\n#allow pick... a selection box is nice but not an option for\r\n#linked files, which would mean 2 different selection options for the user...\r\n# targetWalls = uidoc.Selection.PickElementsByRectangle(selFilt('Self'), 'Drag a selection box')\r\nif option == 1: \r\n pickSel = uidoc.Selection.PickObjects(obt, selFilt('Self'), 'Please pick elements in the model')\r\n #for whatever reason, the selection doesn't return the element\r\n #it returns a Reference, which you can get the Id from, then the element!\r\n for ref in pickSel:\r\n elem = doc.GetElement(ref.ElementId)\r\n targetWalls.append(elem)\r\n ids = targetWalls[0].Id\r\n#if no selection and a linked wall, but not all of them... \r\nelif option == 2: \r\n #pick 1 linked wall\r\n refElemsLinked = uidoc.Selection.PickObjects(obt, \"Please pick elements in the linked model\")\r\n #for our link info later on, we just need 1 wall\r\n refElemLinked = refElemsLinked[0]\r\n for refElemLinked in refElemsLinked:\r\n elem = doc.GetElement(refElemLinked.ElementId)\r\n docLinked = elem.GetLinkDocument()\r\n linkedElement = docLinked.GetElement(refElemLinked.LinkedElementId)\r\n targetWalls.append(linkedElement)\t\r\n ids = targetWalls[0].Id\r\n\r\n#if no selection and all linked walls \r\nelif option == 3:\r\n #get all walls in link instance of selected wall in the view\r\n #sadly the 'active view filter' doesn't work for linked walls, so it's more complex than we'd like\r\n refElemLinked = uidoc.Selection.PickObject(obt, \"Please pick an element in the linked model\")\r\n targetWalls.append(doc.GetElement(refElemLinked.ElementId))\r\n elem = doc.GetElement(refElemLinked.ElementId)\r\n docLinked = elem.GetLinkDocument()\r\n collector = FilteredElementCollector(doc)\r\n fec=ElementCategoryFilter(BuiltInCategory.OST_Walls)\r\n targetWalls = FilteredElementCollector(docLinked,doc.ActiveView.Id).WherePasses(fec).WhereElementIsNotElementType().ToElements()\r\n #walls in model\r\n #targetWalls = FilteredElementCollector(doc, doc.ActiveView.Id).WherePasses(fec).WhereElementIsNotElementType().ToElements()\r\n ids = targetWalls[0].Id\r\n \r\n#if no selection and all walls in doc \r\nelif option == 4:\r\n #get all walls in link instance of selected wall in the view\r\n #sadly the 'active view filter' doesn't work for linked walls, so it's more complex than we'd like\r\n targetWalls = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()\r\n #defining this means we can test against it later\r\n ids = targetWalls[0].Id\r\n\r\n#otherwise, get the walls from the selection\r\n#but if they have selected a link, we need to deal with that, this includes updating the linkedWalls var to True\r\nelse:\r\n for ids in selectedIds:\r\n #if a wall/s or stacked wall/s in the model were selected, go get them\r\n if option == 5:\r\n targetWalls.append(doc.GetElement(ids))\r\n #did they select a link or a wall in a link, we can only get all walls in this instance\r\n elif doc.GetElement(ids).Category.Name == 'RVT Links' and option == 6:\r\n #elem = doc.GetElement(doc.GetElement(ids))\r\n elem = doc.GetElement(ids)\r\n docLinked = elem.GetLinkDocument()\r\n linkElementCollector = FilteredElementCollector(docLinked)\r\n targetWalls = linkElementCollector.OfClass(Wall).ToElements()\r\n \r\n else: \r\n failDialogue = TaskDialog('Fail')\r\n failText = 'Not sure what happened there, let the author know it didn\\'t work' \r\n failDialogue.MainInstruction = failText\r\n failDialogue.Show()\r\n OUT = failText \r\n#return something to the user if they did not select anything\r\nif targetWalls.Count == 0:\r\n failDialogue = TaskDialog('Fail')\r\n failText = 'You did not select any walls, that is not going to work!' \r\n failDialogue.MainInstruction = failText\r\n failDialogue.Show()\r\n OUT = failText\r\n\r\nelse:\r\n #if I cast the selection to a list I find it easier to work with\r\n targetWalls = list(targetWalls)\r\n\r\n #we want the sub-walls from any stacked walls\r\n for tWall in targetWalls:\r\n if tWall.IsStackedWall == True:\r\n targetWalls.extend(doc.GetElement(sub) for sub in tWall.GetStackedWallMemberIds())\r\n\r\n #we then can remove the stacked walls\r\n for tWall in targetWalls:\r\n if tWall.IsStackedWall == True:\r\n targetWalls.remove(tWall)\r\n\r\n #let's go get all the walls for finding references\r\n intersectedWalls = []\r\n intersectedWallsNoTW = []\r\n #then get all the other walls in the view and test if they intersect each wall in the the Target Walls List\r\n #but if we need to look at linked walls, if so, we need a different fec\r\n\r\n #collected walls\r\n #for the linked walls, we have already collected the walls in the select statements above\r\n #we just need to catch the non linked walls\r\n\r\n #if someone has clicked on a link it gives a different output than using the selection!\r\n #it returns an id rather than a reference # \r\n if linkedWalls:\r\n if option == 6:\r\n elem = doc.GetElement(ids)\r\n linkInst = doc.GetElement(ids)\r\n transform = linkInst.GetTotalTransform()\r\n docLinked = elem.GetLinkDocument()\r\n linkElementCollector = FilteredElementCollector(docLinked)\r\n collectedWalls = linkElementCollector.OfClass(Wall).ToElements() \r\n else:\r\n elem = doc.GetElement(refElemLinked.ElementId)\r\n linkInst = doc.GetElement(refElemLinked.ElementId)\r\n docLinked = elem.GetLinkDocument()\r\n transform = linkInst.GetTotalTransform()\r\n collectedWalls = linkedWallsInActiveView(docLinked,refElemLinked, cropShape, solidBaseXYZ, solidTopHt, targetWalls)\r\n \r\n else:\r\n collectedWalls = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()\r\n linkInst = None\r\n\r\n\r\n i = 0\r\n length = len(targetWalls)\r\n while i < length:\r\n #create list here so list structure is correct\r\n intersectedWallsTemp = []\r\n #we want each target wall added to the list\r\n intersectedWallsTemp.append(targetWalls[i])\r\n for collectedWall in collectedWalls:\r\n #add the intersecting walls to the lists\r\n #if the walls are all either in the link or not, they will all have the same intersects?\r\n #it may not be necessary to do any transforms because everything is consistant in itself\r\n #presumably it would only ever be the view cut plane which must be compensated for\r\n if targetWalls[i].Location.Curve.Intersect(collectedWall.Location.Curve) == SetComparisonResult.Overlap:\r\n intersectedWallsTemp.append(collectedWall)\r\n intersectedWalls.append(intersectedWallsTemp)\r\n i = i + 1\r\n\r\n #we are going to need to compensate for transforms here from Links\r\n # p0 = transform.OfPoint(edgeC.GetEndPoint(0))#.ToPoint()\r\n # p1 = transform.OfPoint(edgeC.GetEndPoint(1))#.ToPoint()\r\n #edgeCT = Autodesk.DesignScript.Geometry.Line.ByStartPointEndPoint(p0,p1)\r\n # edgeCT = Line.CreateBound(p0,p1)\r\n # edgeCTNorm = edgeCT.Direction.Normalize()\r\n #get Target Walls external lines for intersect check\r\n exLines = []\r\n for tWall in targetWalls:\r\n exLines.append(locToCutCrv(tWall, wallNormal(tWall, extOrInt), intersectLineEndExtend, projectPos(locName)))\r\n\r\n #Curves where the dimensions will be located\r\n offCrves = []\r\n for exLi, tWall in zip(exLines, targetWalls):\r\n offCrves.append(geom.Geometry.Translate(exLi.ToProtoType(), wallNormal(tWall, extOrInt), (offDist)))\r\n\r\n #lets get the wall edges we want\r\n #only get edges intersecting target side? no this is misleading... we want any reference hitting our external wall\r\n #the problem is actually that the face itsetlf is registering the intersections we don't want e.g. the wrapping ends\r\n frontFacesIW = []\r\n nFrontFaceIW = []\r\n\r\n opts = Options()\r\n #without compute references, none of this works\r\n opts.ComputeReferences = True\r\n #opts.DetailLevel = ViewDetailLevel.Fine\r\n opts.IncludeNonVisibleObjects = True\r\n opts.View = doc.ActiveView\r\n\r\n edgeObj = []\r\n #little list in big list\r\n for intersectedWallsubList in intersectedWalls:\r\n frontFaceIWTemp = []\r\n nFrontFaceIWTemp = []\r\n edgeObjTemp = []\r\n #element in little list\r\n for wallInt in intersectedWallsubList:\r\n #create lists here for correct list structure\r\n #geometry in each element\r\n for obj in wallInt.get_Geometry(opts):\r\n #walls also contain line geometry, only get solids\r\n if isinstance(obj, Solid):\r\n #for each face in obj, so we're expecting to get 1 face per wall in the sub list\r\n for face in obj.Faces:\r\n #if face is normal is equal to wall normal it is the external face\r\n if isAlmostEqualTo(wallInt.Orientation, face.ComputeNormal(UV(0.5,0.5))):\r\n frontFaceIWTemp.append(face)\r\n else:\r\n nFrontFaceIWTemp.append(face)\r\n #this is every edge in all connecting walls\r\n for edge in obj.Edges:\r\n edgeObjTemp.append(edge)\r\n frontFacesIW.append(frontFaceIWTemp)\r\n nFrontFaceIW.append(nFrontFaceIWTemp)\r\n edgeObj.append(edgeObjTemp)\r\n\r\n #testEdgesLines = []\r\n vertEdges = []\r\n for subEd, exLi in zip(edgeObj, exLines):\r\n vertEdgesSub = []\r\n for edge in subEd:\r\n #get edges which intersect\r\n #if front face edge and edge intersects line and edge is vertical up or vertical down add to list\r\n #we have to iterate through the external lines list\r\n edgeC = edge.AsCurve()\r\n edgeCNorm = edgeC.Direction.Normalize()\r\n #intersect isn't working on the linked file\r\n #we will likely need to transform to run the intersect correctly\r\n if linkedWalls:\r\n p0 = transform.OfPoint(edgeC.GetEndPoint(0))#.ToPoint()\r\n p1 = transform.OfPoint(edgeC.GetEndPoint(1))#.ToPoint()\r\n ######\r\n #edgeCT = Autodesk.DesignScript.Geometry.Line.ByStartPointEndPoint(p0,p1)\r\n edgeCT = Line.CreateBound(p0,p1)\r\n #testEdgesLines.append(edgeCT)\r\n edgeCTNorm = edgeCT.Direction.Normalize()\r\n if exLi.Intersect(edgeCT) != SetComparisonResult.Disjoint and (edgeCTNorm.IsAlmostEqualTo(XYZ(0,0,1)) or edgeCTNorm.IsAlmostEqualTo(XYZ(0,0,-1))):\r\n vertEdgesSub.append(edge)\r\n else:\r\n if exLi.Intersect(edgeC) != SetComparisonResult.Disjoint and (edgeCNorm.IsAlmostEqualTo(XYZ(0,0,1)) or edgeCNorm.IsAlmostEqualTo(XYZ(0,0,-1))):\r\n vertEdgesSub.append(edge)\r\n vertEdges.append(vertEdgesSub)\r\n\r\n #so we use the X+Y values as a unique identifier of location (we're less interested in\r\n #the actual unique reference, there may be 2 in the same place)\r\n #we will use these as filtering and sorting values\r\n #if we wanted to use this on sections we'd want to use z value?#\r\n vertEdgesLoc = []\r\n for vertSub in vertEdges:\r\n vertSubTemp = []\r\n for v in vertSub:\r\n vLoc = v.AsCurve().GetEndPoint(0).X + v.AsCurve().GetEndPoint(0).Y\r\n #getting some revit rounding errors, 7dp should be enough!\r\n vertSubTemp.append(round(vLoc,7))\r\n vertEdgesLoc.append(vertSubTemp)\r\n\r\n\r\n #trying to remove stray intersect edges from adjoining walls\r\n #to identify them, they are not on an intersecting wall front face\r\n #their faces are not both on the target wall\r\n\r\n #so we need all the target wall faces\r\n faceTWs = []\r\n for tgWall in targetWalls:\r\n for obj in tgWall.get_Geometry(opts):\r\n #walls also contain line geometry\r\n if isinstance(obj, Solid):\r\n faceTWsSub = obj.Faces\r\n faceTWs.append(faceTWsSub)\r\n\r\n\r\n strayEdges = []\r\n #big lists of front faces & eges\r\n for nFrFaIW, vertEdgesSub, faceTWsub in zip(nFrontFaceIW, vertEdges, faceTWs):\r\n #sub list of front faces, different list length to strayEdgesSub so can't use zip\r\n strayEdgesSub = []\r\n i = 0\r\n length = len(vertEdgesSub)\r\n while (i < length):\r\n #use Get Face on the Edge to see where they've originated from\r\n #we only want edges which are to intersecting wall non-front faces\r\n #this is complicated because we added the target wall to the intersecting wall list\r\n #\r\n if (vertEdgesSub[i].GetFace(0) in nFrFaIW) and (vertEdgesSub[i].GetFace(0) not in faceTWsub):# and ((vertEdgesSub[i].GetFace(1) in nFrFaIW) and (vertEdgesSub[i].GetFace(1) not in faceTWsub)):\r\n strayEdgesSub.append(vertEdgesSub[i])\r\n length = length - 1\r\n #\r\n strayEdgesSub.append(vertEdgesSub[i])\r\n #\r\n length = length - 1\r\n continue\r\n i = i+1\r\n strayEdges.append(strayEdgesSub)\r\n\r\n #if the wall is exterior, we want to remove references to internal wall edge\r\n #do we want to feed ext or int as a list? likely that there will be a mix...\r\n #we could use the wall name (contains ext / int) but there will likely be\r\n #exceptions, which on a large scale makes it error prone\r\n if extOrInt == True:\r\n #all these lists should have the same number of sub lists\r\n for vertEdgesSubLoc, vertSubEdges, straySub in zip(vertEdgesLoc, vertEdges, strayEdges):\r\n i=0\r\n length = len(straySub)\r\n strayCLoc2 = []\r\n while (i < length):\r\n for stray in straySub:\r\n stLoc = stray.AsCurve().GetEndPoint(0).X + stray.AsCurve().GetEndPoint(0).Y\r\n #getting eroneous values, Revit accuracy not good enough? round is built in method\r\n if round(vertEdgesSubLoc[i],7) == round(stLoc,7):\r\n vertSubEdges.Remove(vertSubEdges[i])\r\n vertEdgesSubLoc.Remove(vertEdgesSubLoc[i])\r\n length = length - 1\r\n continue\r\n i = i+1\r\n\r\n #sort the edges using the combined XY location value\r\n vertEdgesLocSorted = []\r\n vertEdgesSorted = []\r\n for vEsubLoc, vSubEdges in zip(vertEdgesLoc, vertEdges):\r\n vertEdgesSubSorted = [x for _,x in sorted(zip(vEsubLoc,vSubEdges))]\r\n vertEdgesSubLocSorted = sorted(vEsubLoc)\r\n vertEdgesLocSorted.append(vertEdgesSubLocSorted)\r\n vertEdgesSorted.append(vertEdgesSubSorted)\r\n\r\n #only add uniquely located references\r\n #this is awkward because we test 1 list, then add to the other list\r\n #we need the Temp list, so we know what should be added to the Sub list\r\n vertEdgeUniLocTemp = []\r\n vertEdgeSub = []\r\n vertEdgeSubRef = ReferenceArray()\r\n\r\n #we want to make sure everything else is working before we get too obsessed by the references#\r\n #this needs to be set for each sub list\r\n #using a def simplifies this#\r\n for vElSubSorted, vEsubSorted in zip(vertEdgesLocSorted, vertEdgesSorted):\r\n vertEdgeSub.append(addInListArray(vElSubSorted, vEsubSorted, linkedWalls, linkInst, doc))\r\n\r\n\r\n #we want to pair up the references to create unique dims for the brick dim checker\r\n #convoluted code, ref arrays seem their own beast!\r\n outRefs = []\r\n for vertEdgeSubTemp in vertEdgeSub:\r\n outRefsSub = []\r\n #define the overall list length\r\n for i in range(vertEdgeSubTemp.Size-1):\r\n #create the array here so the list nesting is correct\r\n vertEdgeAr = ReferenceArray()\r\n #define the sub list length\r\n while vertEdgeAr.Size < 2:\r\n #only get add 2 indices for each sub list\r\n vertEdgeAr.Append(vertEdgeSubTemp[i])\r\n vertEdgeAr.Append(vertEdgeSubTemp[i+1])\r\n outRefsSub.append(vertEdgeAr)\r\n outRefs.append(outRefsSub)\r\n\r\n output = []\r\n #start transaction\r\n TransactionManager.Instance.EnsureInTransaction(doc)\r\n #create dimensions for each pair of referenes in each sub list\r\n\r\n\r\n if multiDim == True:\r\n for refSub, offCrv in zip(outRefs, offCrves):\r\n for ref in refSub:\r\n if ref.Size >= 2:\r\n output.append(doc.Create.NewDimension(doc.ActiveView, offCrv.ToRevitType(), ref))\r\n else:\r\n for refSub, offCrv in zip(vertEdgeSub, offCrves):\r\n #I think we need to catch arrays less that 2 in number, if there is a stacked wall, the lower part might have all\r\n #it's references below the cut plane, so an empty list which fails\r\n if refSub.Size >= 2:\r\n output.append(doc.Create.NewDimension(doc.ActiveView, offCrv.ToRevitType(), refSub))\r\n #finish transaction\r\n TransactionManager.Instance.TransactionTaskDone()\r\n\r\n OUT = targetWalls",
"VariableInputPorts": true,
"Id": "f7c8a5f7279f4ae3abf54c227a7d90b7",
"Inputs": [
{
"Id": "7749ae939890413e81bc76c66ab37d0b",
"Name": "IN[0]",
"Description": "Input #0",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Outputs": [
{
"Id": "0638859e6d1941aa8f4e55cbb9bd65dc",
"Name": "OUT",
"Description": "Result of the python script",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Replication": "Disabled",
"Description": "Runs an embedded IronPython script."
},
{
"ConcreteType": "PythonNodeModels.PythonNode, PythonNodeModels",
"NodeType": "PythonScriptNode",
"Code": "#thanks to Ben Robinson\r\n#alternatitvely you can load the XAML file using PresentationFramework in presentationframework but with some limitations\r\n\r\nimport clr\r\nimport sys\r\npyt_path = r'C:\\Program Files (x86)\\IronPython 2.7\\Lib'\r\nsys.path.append(pyt_path)\r\n\r\n#############-------------\\-------------##############\r\n\r\n ### UI additional references ###\r\n \r\nclr.AddReference(\"System.Windows.Forms\")\r\nclr.AddReference(\"System.Drawing\")\r\n\r\nfrom System.Windows.Forms import Application, Form, FormWindowState, Screen, Label, PictureBox, PictureBoxSizeMode, AnchorStyles, BorderStyle, ComboBox, ComboBoxStyle, FormBorderStyle, CheckBox, TextBox, TextBoxBase\r\nfrom System.Windows.Forms import Button, LinkLabel, Panel, Button\r\nfrom System.Drawing import Icon, Color, Font, Point, Size#, Image\r\n\r\n#system location C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\r\nimport System.IO\r\n\r\n# Import DocumentManager and TransactionManager #\r\nclr.AddReference(\"RevitServices\")\r\nimport RevitServices\r\nfrom RevitServices.Persistence import DocumentManager\r\nfrom RevitServices.Transactions import TransactionManager\r\n\r\ndoc = DocumentManager.Instance.CurrentDBDocument\r\nuidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument\r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Define some variables ###\r\n\r\n#these variables are static through the 2 windows\r\nbitmapImage = System.Drawing.Bitmap(\"C:\\Me\\Dynamo\\WPF in Dynamo\\\\\" + \"dyna-sco-logo.png\") #titlebar logo as bmp\r\ntitleIcon = Icon.FromHandle(bitmapImage.GetHicon()) #titlebar logo as icon\r\ntitleText = \"Dimensioning\" #text that appears in the GUI titlebar\r\nbtnHeight = 40 #declared here as used for btn locations\r\nbtnWidth = 120\r\nspacing = 20 #spacing size for GUI elements to form a consistent border\r\nfontMessage = Font(\"Helvetica \", 9)\r\nfontCK = Font(\"Helvetica \", 8) #set Checkbox Font\r\nwinSize = Size(1000,600) #consistant window size\r\n\r\nrun = IN[0][0]\r\nlinkedWalls = IN[0][1]\r\nallWalls = IN[0][2]\r\nextWalls = IN[0][3]\r\nmultiDim = IN[0][4]\r\ncoordSysName = IN[0][5]\r\noffsetDist = IN[0][6]\r\n\r\n#See if there's anything selected\r\nselectedIds = uidoc.Selection.GetElementIds()\r\n\r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Global defs ###\r\n \r\ndef button(txt, loc, clc):\r\n btn = Button()\r\n #btnCancel.Parent = self\r\n btn.Text = txt\r\n btn.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right)\r\n btn.Location = loc\r\n btn.Click += clc\r\n btn.Height = btnHeight\r\n btn.Width = btnWidth\r\n btn.BackColor = Color.FromArgb(220, 220, 220)\r\n return btn\r\n\r\ndef logo(uiW, uiH):\r\n logo = PictureBox()\r\n bitmapImage = System.Drawing.Bitmap(\"C:\\Me\\Dynamo\\WPF in Dynamo\\\\\" + \"dyna-sco-logo-text.png\") \r\n logo.Image = bitmapImage\r\n ratio = float(logo.Height)/ float(logo.Width) #needs to be a float as int will round to the nearest whole number\r\n logo.Size = Size(220, 130*ratio) #fixed for consistancy\r\n logo.Location = Point(spacing, (uiH - logo.Height)-spacing)\r\n logo.SizeMode = PictureBoxSizeMode.Zoom # zooms the image to fit the extent\r\n logo.Anchor = (AnchorStyles.Bottom | AnchorStyles.Left) #anchor styles lock elements to a given corner of the GUI if you allow users change size\r\n return logo\r\n\r\n\r\nclass message():\r\n def __init__(self):\r\n 'test'\r\n# self.messText = 'message'\r\n def messTxt(self, selectedIds, linkedWalls, allWalls): #the __init__ method inside a class is its constructor\r\n# self.messText = 'message'\r\n# return self.messText\r\n if selectedIds.Count == 0 and not linkedWalls and not allWalls:\r\n self.messText = 'There was nothing selected, click ok, then click non-linked walls. \\n\\nThen click Finish in the top left to dimension them'\r\n self.outSel = 1\r\n elif selectedIds.Count == 0 and linkedWalls and not allWalls:\r\n self.messText = 'There was nothing selected (or you picked linked walls which doesn\\'t work for this). \\n\\nYou chose to dimension linked walls, in the active view, click ok, then go ahead and click them. \\n\\nThen click Finish in the top left'\r\n self.outSel = 2\r\n elif selectedIds.Count == 0 and linkedWalls and allWalls:\r\n self.messText = 'There was nothing selected, you choose to dimension All linked walls, in the active view. \\n\\nClick ok, then click a wall in the link you are interested in.'\r\n self.outSel = 3\r\n elif selectedIds.Count == 0 and not linkedWalls and allWalls:\r\n self.messText = 'There was nothing selected, you choose to dimension All (not linked) walls in the active view'\r\n self.outSel = 4\r\n else:\r\n for ids in selectedIds:\r\n if doc.GetElement(ids).Category.Name == 'Walls'or doc.GetElement(ids).Category.Name == 'Stacked Walls':\r\n self.messText = 'We will now dimension your selection'\r\n self.outSel = 5\r\n else:\r\n self.messText = 'You pre selected a link so All it\\'s walls in the view will be dimensioned'\r\n self.outSel = 6\r\n return self.messText, self.outSel\r\n\r\n \r\n##########################-------------\\-------------##########################\r\n\r\n ### Create a Class to define the second window ####\r\n\r\nclass followForm(Form):\r\n\r\n def __init__(self): #the __init__ method inside a class is its constructor\r\n self.runNextOutput = False #how we decide if we want the next window to fire \r\n \r\n self.Text = titleText \r\n self.Icon = titleIcon \r\n self.Size = winSize\r\n self.CenterToScreen()\r\n self.FormBorderStyle = FormBorderStyle.FixedDialog \r\n \r\n uiWidth = self.DisplayRectangle.Width #get the size of the form to use to scale form elements\r\n uiHeight = self.DisplayRectangle.Height\r\n self.Controls.Add(logo(uiWidth, uiHeight)) #add logo \r\n \r\n#############-------------\\-------------############# \r\n\r\n ### Buttons ## \r\n\r\n #Create Ok Button\r\n btnOkClick = self.okButtonPressed #register click by user\r\n btnOkLoc = Point(uiWidth - ((btnWidth * 2) + spacing + 30), uiHeight - (btnHeight + spacing))\r\n btnOk = button('OK', btnOkLoc, btnOkClick) \r\n\r\n #Create Cancel Button\r\n btnCnclClick = self.CnlButtonPressed #register click by user\r\n btnCnclLoc = Point(uiWidth - (btnHeight + spacing + 90), uiHeight - (btnHeight + spacing ))\r\n btnCancel = button('Cancel', btnCnclLoc, btnCnclClick)\r\n \r\n #add to Window\r\n self.Controls.Add(btnOk)\r\n self.Controls.Add(btnCancel) \r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Create Second Window Text ###\r\n \r\n userMessageScnd = Label() #label displays texts\r\n font = fontMessage\r\n messageTest = message().messTxt(selectedIds, linkedWalls, allWalls)\r\n userMessageScnd.Text = messageTest[0] \r\n self.selOut = messageTest[1]\r\n #userMessageScnd.Text = dimsionInputs().messText\r\n userMessageScnd.Font = font\r\n userMessageScnd.Location = Point(spacing, spacing) #all location require a point object from system.Drawing to set the location.\r\n userMessageScnd.Size = Size(uiWidth-(spacing*2),(uiHeight)) #size the control with the width of the GUI to ensure it scales with different screen\r\n self.Controls.Add(userMessageScnd) #this adds control element to the GUI\r\n\r\n#############-------------\\-------------#############\r\n\r\n ### Return Info From User ##\r\n \r\n ### buttons ###\r\n def okButtonPressed(self, sender, args):\r\n self.Close() #trigger to close the GUI when button is pressed\r\n self.runNextOutput = True #if the ok button is pressed set runNextOutput as True#\r\n def CnlButtonPressed(self, sender, args):\r\n self.Close()\r\n\r\n##########################-------------\\-------------##########################\r\n\r\n\r\n ### And Run ##\r\n\r\nfollowForm = followForm() \r\n\r\nif run:\r\n Application.Run(followForm)\r\n OUT = followForm.runNextOutput, followForm.selOut, extWalls, multiDim, coordSysName, offsetDist\r\nelse:\r\n OUT = 'did not run'",
"VariableInputPorts": true,
"Id": "b54f6e23331c48d3a55883743708a8a8",
"Inputs": [
{
"Id": "2e29c54a94b043079feb153c4ac1c078",
"Name": "IN[0]",
"Description": "Input #0",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Outputs": [
{
"Id": "62856b257bdc4f57a8e3986391ddf58c",
"Name": "OUT",
"Description": "Result of the python script",
"UsingDefaultValue": false,
"Level": 2,
"UseLevels": false,
"KeepListStructure": false
}
],
"Replication": "Disabled",
"Description": "Runs an embedded IronPython script."
}
],
"Connectors": [
{
"Start": "a0b66b724e764136bb41244cda3b06c9",
"End": "e76381f7d18b41d78620a9cb93c838ab",
"Id": "eecd1ae4174c49e78483885727463be3"
},
{
"Start": "1ced077741d24e159afd44adc3c66516",
"End": "2e29c54a94b043079feb153c4ac1c078",
"Id": "0f49d1d59b974add84a24a9e39ae9b86"
},
{
"Start": "62856b257bdc4f57a8e3986391ddf58c",
"End": "7749ae939890413e81bc76c66ab37d0b",
"Id": "5d4b36cf8d354f7d8c582707dfb8e5eb"
}
],
"Dependencies": [],
"NodeLibraryDependencies": [],
"Bindings": [],
"View": {
"Dynamo": {
"ScaleFactor": 1.0,
"HasRunWithoutCrash": true,
"IsVisibleInDynamoLibrary": true,
"Version": "2.5.0.7460",
"RunType": "Manual",
"RunPeriod": "1000"
},
"Camera": {
"Name": "Background Preview",
"EyeX": -17.0,
"EyeY": 24.0,
"EyeZ": 50.0,
"LookX": 12.0,
"LookY": -13.0,
"LookZ": -58.0,
"UpX": 0.0,
"UpY": 1.0,
"UpZ": 0.0
},
"NodeViews": [
{
"ShowGeometry": true,
"Name": "Refresh",
"Id": "ea4ea2090366416c9b6745d4d181eebb",
"IsSetAsInput": false,
"IsSetAsOutput": false,
"Excluded": false,
"X": 71.9999999999999,
"Y": 148.799999999999
},
{
"ShowGeometry": true,
"Name": "Winform 1",
"Id": "aab1c51701d84489a86dbbb44a8a919a",
"IsSetAsInput": false,
"IsSetAsOutput": false,
"Excluded": false,
"X": 274.873432713886,
"Y": 148.799999999999
},
{
"ShowGeometry": true,
"Name": "Lnks WinFrms",
"Id": "f7c8a5f7279f4ae3abf54c227a7d90b7",
"IsSetAsInput": false,
"IsSetAsOutput": false,
"Excluded": false,
"X": 678.995426897698,
"Y": 148.799999999999
},
{
"ShowGeometry": true,
"Name": "Winform 2",
"Id": "b54f6e23331c48d3a55883743708a8a8",
"IsSetAsInput": false,
"IsSetAsOutput": false,
"Excluded": false,
"X": 484.58554655601739,
"Y": 149.86995811873271
}
],
"Annotations": [
{
"Id": "9ea34d3f58184375ab9f753ef21e7084",
"Title": "Dimension Walls In Plan",
"Nodes": [
"b54f6e23331c48d3a55883743708a8a8",
"f7c8a5f7279f4ae3abf54c227a7d90b7",
"aab1c51701d84489a86dbbb44a8a919a",
"ea4ea2090366416c9b6745d4d181eebb"
],
"Left": 61.9999999999999,
"Top": 95.599999999998985,
"Width": 751.39542689769814,
"Height": 146.86995811873373,
"FontSize": 36.0,
"InitialTop": 148.799999999999,
"InitialHeight": 145.0,
"TextblockHeight": 43.2,
"Background": "#FFC1D676"
}
],
"X": -277.36871854058313,
"Y": 82.347472336884778,
"Zoom": 0.74769281712332525
}
}