Posts by retug (38)

RAM API - Cracked

I finally cracked into the RAM Structural System API after maybe 3 years of wanting to get into it.

The key to getting in? More powerful googling. 

Googling "RAM Structural API" yields some very uninspiring result. Usually the results pointed to the RAM Structural API documentation that looks very cryptic and appears to require C++ as coding language. A few snips from the API documentation. 

All of this looked pretty intimidating and I had about 0 desire to learn a new programming language. I put learning the RAM API on the backburner even though this is our offices daily driver for most buildings.

Marcello Sgambelluri to the Rescue

One day I happened to stumble on a post on Autodesk's forum regarding RAM API access by Marcello. I knew Macello's name and I knew this would be the ticket to getting into the API. He always does a great job of documenting his madness.

A link to the material that cracked the API.

Following this link is kinda crazy. Never in my wildest dreams would I imagine that cracking the RAM API would involve some tech with Revit, Dynamo and C#... the whole RAM API documentation is in C++!! How, why? Seriously if you have an answer to how Marcello was able to access the API with C# and not C++, let me know, there is not a single mention of C# in the documentation. Maybe all .net languages can be intertwined??

Anyways, Marcello's examples utilize C# and something called zero touch nodes in dyanmo to unlock the RAM API. The examples are quite helpful and I can't wait to dig in deeper to see what the API might unlock.

I have posted the code on github. The hardest part was not the code, but setting up all the references in the visual studio IDE and getting the code to successfully compile. After some tweaking on the settings, I was able to get a successful build. 

Upon loading the .dll (a .dll file is the compiled code as I understand it) into dynamo, you feed the file name into the "node" and the code returns the total number of stories in your RAM structural model. This is a simple example, but opens the doors to so much more.

The picture above correctly returns the number of stories in the sample RAM structural model I fed to it. HOW COOL IS THAT!

 

Moving forward, I hope to keep digging into the RAM API, exploring more of Marcello's examples and building some code of my own to automate tasks in RAM Structural. 

ETABs API - More Examples (Database Tables)

Sparked by a reddit inquiry, I have added an example on my github to access the database table results using the ETABs API. The python code can be found on github.

The Code

The example code works to access the joint reaction database table results from ETABs v20.

 

In the image above, you can see that the python code pulls the correct vertical reaction when looking at the dead load reaction (3.177 kips). The python code returns results in pounds, but you can easily format your result units with SapModel.SetPresentUnits(x). The ETABs API document gives a good run down on all the units available.

Website Database Scare

On Decemeber 10th, I logged into my website to be greeted by a scary error message

I had not done anything to the site, so I figured something bad more than likely happened.

The work week was busy, so I was not able to start troubleshooting until December 17th. Running the command heroku logs --tail  led to message that stated:

File "/app/my_website/settings.py", line 108, in <module> raise Exception("DATABASE_URL environment variable not defined") Exception: DATABASE_URL environment variable not defined

Reading this, I knew the database had somehow gotten disconnected. Logging into heroku where I host the website and database, I was greeted with a scary red warning label:

At this point, real panic sets in, what happened to my database? I knew that I was paying heroku to host my website, so I thought was just a warning they were putting on all dashboards. At this point, I open up the 10 emails I received from heroku stating that they are removing free hosting and database services. After some research, I realized that I was paying for the server, but not for the database; I was still using the free tier postgres database. 

Tail tucked between my legs, I follow heroku's "hey you dummy, you ignored all of our emails and you want to get your website back" tutorial and within 4 hours of opening a ticket and 9 bucks later, my database was restored.

The take away

DONT IGNORE IMPORTANT EMAILS!

One Way Load Distribution In ETABs

I have used ETABs one way load distribution button for a long time and it works great on flat floors and "slightly sloped roof" to distribute load based on tributary area.

Today though, a coworker of mine noticed on a slightly more pitched roof, angle of about 30 degrees, the one way loading was not working as intended (could not see applied loading due to tributary area).

I built a test model to explore the odd behavior.

Slab section properties uses one way distribution:

(3) sample floors are made, each with the same load and beam restraint layout, but you can see, once the floor becomes "too sloped", the load distribution switches from a line load on the frame elements to merely point loads applied at the edge of the membrane

 

The magic slope where this seems to occur is about 20 degrees from horizontal. 

Edit 2024-10-22

It appears that this 20 degree number is in the Set Tolerances button of ETABs, tweak away.



Hopefully this post saves someone in the future the pains of troubleshooting this odd behavior

Ray Caster Algorithm

Now that the user interface for the concrete tool is up and running, I need to start working on the concrete analysis.

The first order of business is a meshing algorithm for the concrete shape. 

I do not know exactly which direction this meshing algorithm is going to head, but every direction I look, it appears as though I will need some code to check if a given point falls within an enclosed polygon. The pretty pictures above show the code in action, if the point falls within the polygon, it is painted green, if not, red.

After some research, it appeared as though the ray caster algorithm would be the ticket to solve this problem. 

The code to check if the point falls within any given abritary polygon is shown below:

function ray_casting(point, testPoly, holePolys) {
  var n = testPoly.length;
  var count = 0
  var holeCount = 0
  var x = point[0];
  var y = point[1];
  

for(var i=0; i <n; ++i) {
    if (i == n-1) {
      var side = {
        a: {
          x: testPoly[i][0],
          y: testPoly[i][1]
        },
        b: {
          x: testPoly[0][0],
          y: testPoly[0][1]
        }
      }
        var x1 = side.a.x
        var x2 = side.b.x
        var y1 = side.a.y
        var y2 = side.b.y
        if (y < y1 != y < y2 && x < (x2-x1)*(y-y1)/ (y2-y1)+x1) {
        count +=1
      }
    }
    else {
      var side = {
        a: {
          x: testPoly[i][0],
          y: testPoly[i][1]
        },
        b: {
          x: testPoly[i+1][0],
          y: testPoly[i+1][1]
        }
      }
      var x1 = side.a.x
      var x2 = side.b.x
      var y1 = side.a.y
      var y2 = side.b.y
      if (y < y1 != y < y2 && x < (x2-x1)*(y-y1)/ (y2-y1)+x1) {
        count +=1
      }
    }
  }
  for (var holePoly of holePolys) {
    var nHole = holePoly.length;
    for(var i=0; i <nHole; ++i) {
      if (i ==nHole-1){
        var side = {
          a: {
            x: holePoly[i][0],
            y: holePoly[i][1]
          },
          b: {
            x: holePoly[0][0],
            y: holePoly[0][1]
          }
        }
        var x1 = side.a.x
        var x2 = side.b.x
        var y1 = side.a.y
        var y2 = side.b.y
        if (y < y1 != y < y2 && x < (x2-x1)*(y-y1)/ (y2-y1)+x1) {
          holeCount +=1
        }
      }
      else{
        var side = {
          a: {
            x: holePoly[i][0],
            y: holePoly[i][1]
          },
          b: {
            x: holePoly[i+1][0],
            y: holePoly[i+1][1]
          }
        }
        var x1 = side.a.x
        var x2 = side.b.x
        var y1 = side.a.y
        var y2 = side.b.y
        if (y < y1 != y < y2 && x < (x2-x1)*(y-y1)/ (y2-y1)+x1) {
          holeCount +=1
        }
      }
    }
  }
  if (count % 2 == 0 || count == 0 ) {
    return [false, count, holeCount]
  }
  else if (holeCount % 2 == 1) {
    return [false, count, holeCount]
  }
  else {
    return [true, count, holeCount]
  }
}

The algorithm is very simple, given a point, cast an inifinite line to the right. If the line crosses the polygon an even number of times, the point is outside the polygon.

Adding in some more code to test for holes and we are able to quickly tell if the point is inside or outisde the polygon with holes.

The code can be found on github.

A tease for the future:

First Previous 3 4 5 6 7 Next Last

Sidebar

Site Info

  • Latest Comments