1111using System ;
1212using System . Collections . Generic ;
1313using System . Diagnostics ;
14+ using System . Linq ;
1415using Autodesk . Revit . ApplicationServices ;
1516using Autodesk . Revit . Attributes ;
1617using Autodesk . Revit . DB ;
1920
2021namespace BuildingCoder
2122{
22- [ Transaction ( TransactionMode . ReadOnly ) ]
23+ [ Transaction ( TransactionMode . Manual ) ]
2324 class CmdBoundingBox : IExternalCommand
2425 {
26+ /// <summary>
27+ /// XYZ wrapper class implementing IComparable.
28+ /// </summary>
29+ class XyzComparable : XYZ , IComparable < XYZ >
30+ {
31+ public XyzComparable ( XYZ a )
32+ : base ( a . X , a . Y , a . Z )
33+ {
34+ }
35+
36+ int IComparable < XYZ > . CompareTo ( XYZ a )
37+ {
38+ return Util . Compare ( this , a ) ;
39+ }
40+ }
41+
42+ /// <summary>
43+ /// Return a rotated bounding box around
44+ /// the origin in the XY plane.
45+ /// We cannot just rotate the min and max points,
46+ /// because the rotated max point may easily end
47+ /// up being 'smaller' in some coordinate than the
48+ /// min. To work around that, we extract all four
49+ /// bounding box corners, rotate each of them and
50+ /// determine new min and max values from those.
51+ /// </summary>
52+ private static BoundingBoxXYZ RotateBoundingBox (
53+ BoundingBoxXYZ b ,
54+ Transform t )
55+ {
56+ double height = b . Max . Z - b . Min . Z ;
57+
58+ // Four corners: lower left, lower right,
59+ // upper right, upper left:
60+
61+ XYZ [ ] corners = Util . GetCorners ( b ) ;
62+
63+ XyzComparable [ ] cornersTransformed
64+ = corners . Select < XYZ , XyzComparable > (
65+ p => new XyzComparable ( t . OfPoint ( p ) ) )
66+ . ToArray ( ) ;
67+
68+ b . Min = cornersTransformed . Min ( ) ;
69+ b . Max = cornersTransformed . Max ( ) ;
70+ b . Max += height * XYZ . BasisZ ;
71+
72+ return b ;
73+ }
74+
2575 public Result Execute (
2676 ExternalCommandData commandData ,
2777 ref string message ,
@@ -40,7 +90,7 @@ public Result Execute(
4090 return Result . Failed ;
4191 }
4292
43- // trying to call this property returns the
93+ // Trying to call this property returns the
4494 // compile time error: Property, indexer, or
4595 // event 'BoundingBox' is not supported by
4696 // the language; try directly calling
@@ -66,20 +116,46 @@ public Result Execute(
66116 }
67117 else
68118 {
69- Debug . Assert ( b . Transform . IsIdentity ,
70- "expected identity bounding box transform" ) ;
71-
72- string in_view = ( null == v )
73- ? "model space"
74- : "view " + v . Name ;
75-
76- Util . InfoMsg ( string . Format (
77- "Element bounding box of {0} in "
78- + "{1} extends from {2} to {3}." ,
79- Util . ElementDescription ( e ) ,
80- in_view ,
81- Util . PointString ( b . Min ) ,
82- Util . PointString ( b . Max ) ) ) ;
119+ using ( Transaction tx = new Transaction ( doc ) )
120+ {
121+ tx . Start ( "Draw Model Line Bounding Box Outline" ) ;
122+
123+ Debug . Assert ( b . Transform . IsIdentity ,
124+ "expected identity bounding box transform" ) ;
125+
126+ string in_view = ( null == v )
127+ ? "model space"
128+ : "view " + v . Name ;
129+
130+ Util . InfoMsg ( string . Format (
131+ "Element bounding box of {0} in "
132+ + "{1} extends from {2} to {3}." ,
133+ Util . ElementDescription ( e ) ,
134+ in_view ,
135+ Util . PointString ( b . Min ) ,
136+ Util . PointString ( b . Max ) ) ) ;
137+
138+ Creator creator = new Creator ( doc ) ;
139+
140+ creator . DrawPolygon ( new List < XYZ > (
141+ Util . GetCorners ( b ) ) ) ;
142+
143+ Transform rotation = Transform . CreateRotation (
144+ XYZ . BasisZ , 60 * Math . PI / 180.0 ) ;
145+
146+ b = RotateBoundingBox ( b , rotation ) ;
147+
148+ Util . InfoMsg ( string . Format (
149+ "Bounding box rotated by 60 degrees "
150+ + "extends from {0} to {1}." ,
151+ Util . PointString ( b . Min ) ,
152+ Util . PointString ( b . Max ) ) ) ;
153+
154+ creator . DrawPolygon ( new List < XYZ > (
155+ Util . GetCorners ( b ) ) ) ;
156+
157+ tx . Commit ( ) ;
158+ }
83159 }
84160 return Result . Succeeded ;
85161 }
0 commit comments