{"id":264,"date":"2023-08-21T00:30:29","date_gmt":"2023-08-20T22:30:29","guid":{"rendered":"https:\/\/easyrevitapi.com\/?p=264"},"modified":"2023-10-22T14:24:16","modified_gmt":"2023-10-22T12:24:16","slug":"solids-and-transformations","status":"publish","type":"post","link":"https:\/\/easyrevitapi.com\/index.php\/2023\/08\/21\/solids-and-transformations\/","title":{"rendered":"Transforming solids"},"content":{"rendered":"\n<p>When using the Revit API, we often perform tasks involving multiple geometries. For instance, we might compare their positions or identify their intersections. However, it&#8217;s important to note that even if these geometries appear close in the Revit 3D space, they could be related to different coordinate systems. In this case, comparing these geometries while referring to their respective coordinates might give us incorrect results. <\/p>\n\n\n\n<p>I once had to write a script that checked whether MEP elements from a linked model had the exact same position as those in the host model. Curiously, even when Revit displayed all elements to be aligned, the script&#8217;s results expressed the opposite. I eventually figured out that each model positioned its elements differently in relation to the internal origin, leading to incorrect results. Although, the elements of both models had the same position to the project base point, which explained the visual alignment. <\/p>\n\n\n\n<p>A way of solving similar problems is by using the revit transformations and applying them to the geometries. They allow to convert a geometry&#8217;s coordinates from one system to another. Beyond this case, transformations are also useful to simply move a geometry within one same Revit model, with no consideration to multiple coordinate systems.<\/p>\n\n\n\n<p>Before going further, you might want to understand more about Revit transformations. For more insights, please refer to the preceding article : <a href=\"https:\/\/easyrevitapi.com\/index.php\/2023\/08\/15\/revit-transformations-made-easy\/\" data-type=\"link\" data-id=\"https:\/\/easyrevitapi.com\/index.php\/2023\/08\/15\/revit-transformations-made-easy\/\">Revit Transformations Made Easy<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Moving the solid<\/h4>\n\n\n\n<p>For a better understanding of how transformations are applied to geometries in Revit, let&#8217;s consider a simple example : translating and rotating a wall. We begin by defining a method that takes the wall&#8217;s geometry as an argument, applies the desired translation and rotation to it, and then returns the resultant geometry. We&#8217;ll name this method <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-3-color\">TransformSolid()<\/mark>.<\/p>\n\n\n\n<p>We will be using three classes provided by the Revit API :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Transform<\/mark> <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">:<\/mark> a class that holds the instructions for moving a point or a geometry in the 3D space. <\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Solid<\/mark> : a class that represents the geometric data of any object modeled in Revit.<\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">SolidUtils<\/mark> : a class that performs multiple operations related to solids, among which the application of transformations using the static method <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-3-color\">SolidUtils.CreateTransformed()<\/mark>.<\/li>\n<\/ul>\n\n\n\n<p>While this example involves a basic geometry, the same approach can be used for more intricate ones.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"721\" src=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-1024x721.jpg\" alt=\"\" class=\"wp-image-270\" style=\"width:639px;height:450px\" srcset=\"https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-1024x721.jpg 1024w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-300x211.jpg 300w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-768x540.jpg 768w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-1536x1081.jpg 1536w, https:\/\/easyrevitapi.com\/wp-content\/uploads\/2023\/08\/Transformation-2-2048x1441.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#002B36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"    public class Transformations\n    {\n        public static Solid TransformSolid(Solid wallSolid)\n        {\n            XYZ translationVector = new XYZ(3, 5, 0);\n            XYZ rotationAxis = new XYZ(0, 0, 1);\n            XYZ pointO = new XYZ(8, 10, 0);\n\n            double rotationAngle = 1.5707963268; \/\/ Unit is in Radian\n\n            \/\/ Defining the rotation and translation transformations\n            Transform transform_Translation = Transform.CreateTranslation(translationVector);\n            Transform transform_Rotation = Transform.CreateRotationAtPoint(rotationAxis, rotationAngle, pointO);\n\n            \/\/ Combining the transformations \n            Transform transform_TranslationPlusRotation = transform_Rotation.Multiply(transform_Translation);\n            \n            \/\/ Using the SolidUtils.CreateTransformed() static method to apply the transformation on the solid\n            Solid transformedSolid = SolidUtils.CreateTransformed(wallSolid, transform_TranslationPlusRotation);\n\n            return transformedSolid;\n        }\n\n    }\" style=\"color:#839496;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki solarized-dark\" style=\"background-color: #002B36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #839496\">    <\/span><span style=\"color: #93A1A1; font-weight: bold\">public<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #93A1A1; font-weight: bold\">class<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #CB4B16\">Transformations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #93A1A1; font-weight: bold\">public<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #93A1A1; font-weight: bold\">static<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #CB4B16\">Solid<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">TransformSolid<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #CB4B16\">Solid<\/span><span style=\"color: #839496\"> wallSolid)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\"> translationVector <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #859900\">new<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #D33682\">3<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">5<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\"> rotationAxis <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #859900\">new<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">1<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\"> pointO <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #859900\">new<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #CB4B16\">XYZ<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #D33682\">8<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">10<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #859900\">double<\/span><span style=\"color: #839496\"> rotationAngle <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #D33682\">1.5707963268<\/span><span style=\"color: #839496\">; <\/span><span style=\"color: #586E75; font-style: italic\">\/\/ Unit is in Radian<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\">            \/\/ Defining the rotation and translation transformations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">Transform<\/span><span style=\"color: #839496\"> transform_Translation <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">Transform<\/span><span style=\"color: #839496\">.<\/span><span style=\"color: #268BD2\">CreateTranslation<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #268BD2\">translationVector<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">Transform<\/span><span style=\"color: #839496\"> transform_Rotation <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">Transform<\/span><span style=\"color: #839496\">.<\/span><span style=\"color: #268BD2\">CreateRotationAtPoint<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #268BD2\">rotationAxis<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #268BD2\">rotationAngle<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #268BD2\">pointO<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\">            \/\/ Combining the transformations <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">Transform<\/span><span style=\"color: #839496\"> transform_TranslationPlusRotation <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">transform_Rotation<\/span><span style=\"color: #839496\">.<\/span><span style=\"color: #268BD2\">Multiply<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #268BD2\">transform_Translation<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\">            \/\/ Using the SolidUtils.CreateTransformed() static method to apply the transformation on the solid<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #CB4B16\">Solid<\/span><span style=\"color: #839496\"> transformedSolid <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">SolidUtils<\/span><span style=\"color: #839496\">.<\/span><span style=\"color: #268BD2\">CreateTransformed<\/span><span style=\"color: #839496\">(<\/span><span style=\"color: #268BD2\">wallSolid<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #268BD2\">transform_TranslationPlusRotation<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #859900\">return<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">transformedSolid<\/span><span style=\"color: #839496\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    }<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Converting the coordinates<\/h4>\n\n\n\n<p>So far we have seen how to apply a transformation to a <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Solid<\/mark>. This same approach is actually used to convert a geometry&#8217;s coordinates between two distinct Revit models that have different coordinate systems. The question now is : how do we find the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Transform <\/mark>object we need to make such conversion.<\/p>\n\n\n\n<p>In the Revit API, Linked models are represented by two classes : <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">RevitLinkType<\/mark> and <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">RevitLinkInstance<\/mark>. The latter actually provides a method to retrieve the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Transform <\/mark>object we seek : <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-3-color\">RevitLinkInstance.GetTransform()<\/mark>. let&#8217;s identify this object as <strong>linkModelTransform<\/strong>.  <\/p>\n\n\n\n<p>To convert the geometry&#8217;s coordinates <span style=\"text-decoration: underline;\">from the linked model&#8217;s system to the host model&#8217;s system<\/span> : we can directly use <strong>linkModelTransform<\/strong> as an argument for the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-3-color\">SolidUtils.CreateTransformed()<\/mark> method.<\/p>\n\n\n\n<p>To convert the geometry&#8217;s coordinates <span style=\"text-decoration: underline;\">from the host model&#8217;s system to the linked model&#8217;s system<\/span>, we must instead use the <span style=\"text-decoration: underline;\">inverse<\/span> of <strong>linkModelTransform<\/strong>. <\/p>\n\n\n\n<p>An inverse <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Transform<\/mark> object holds the &#8220;opposite&#8221; transformations, and is obtained using the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-3-color\">linkModelTransform.inverse <\/mark><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-6-color\">property.<\/mark><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Conclusion<\/h4>\n\n\n\n<p>Beyond the conversion of coordinates from one system to another, the application of transformations to geometries represents a foundation for more complex tasks. Once you begin using them, you quickly understand the freedom and the new possibilities they enable when working with geometric data. Now go and build stuff. Have fun \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When using the Revit API, we often perform tasks involving multiple geometries. For instance, we might compare their positions or identify their intersections. However, it&#8217;s important to note that even if these geometries appear close in the Revit 3D space, they could be related to different coordinate systems. In this case, comparing these geometries while [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1029,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-264","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-geometry"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/comments?post=264"}],"version-history":[{"count":40,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/264\/revisions"}],"predecessor-version":[{"id":1255,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/posts\/264\/revisions\/1255"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/media\/1029"}],"wp:attachment":[{"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/media?parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/categories?post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/easyrevitapi.com\/index.php\/wp-json\/wp\/v2\/tags?post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}