Posts by retug (37)

Autodesk Platform Services - A First Step

I'm not really sure what Autodesk Platform Services is or why I should use it, but Autodesk is pushing this hard it seems. The tech looks cool so I figured I would follow their first tutorial.

The first example they provide on APS is how to upload your local revit model to their cloud service and view the revit model in your web browser. Really cool! The example model shown in the gif above was the same model I built to show off the RAM to Revit tool.

A Return to Javascript

The documentation, found here on autodesk's github and the web example, is really well put together, I just made one stupid error that cost me about 4 hours of debugging and one stupid post to stackoverflow to try to solve. I have been meaning to come back to the concrete design tool for awhile which is written in javascript, so when I saw the tutorial recommended node.js and javascript as the first option, I hopped on the oppurtunity to refresh the javascript skills.

A few blog posts ago, I think I mentioned that one day I hope to experience less "firsts" in programming, this was a great example of less "firsts". I had played with all the tech stacks they utilized in the example, node.js, npm, javascript were all at least somewhat familiar to me. Finally! No watching 10 hrs of videos just to have a basic understanding of where we need to begin. 

Also, APS is built using three.js which I have experience with in building the about page on the website as well as the concrete design tool, how cool! It's crazy how all these tech stacks build on top of each other, finally starting to feel like a semi-experienced programmer.

APS Tutorial

As I had mentioned, the APS turorial was really well put together, but I will highlight a few things I found a bit unclear for my beginner programmer mindset.

First, make sure you are using powershell if you are on windows to input the commands in the documentation. Originally I was in git, which was not the right spot. The image below you can see git was working, but eventually I realized I needed to be in powershell.

The code is pretty advanced, so a lot of times where I had absolutely no I idea what I was copying and pasting. Throwing the code into chatgpt and asking it to explain it to me was helpful.

At the authentication step of the process, the docuemtation mentions that you should be greeted with a window that I was not getting. I should have realized that I had made a mistake and went back to fix it, but instead I forged (pun intended, APS used to be known as Forge) on to make my previous mistake much worse.

My mistake, in the .env file, you are supposed to store your APS_CLIENT_ID and APS_CLIENT_SECRET in a string. 
The code that is put up on the website looks like this:

APS_CLIENT_ID="<client-id>"
APS_CLIENT_SECRET="<client-secret>"

I replaced this as

APS_CLIENT_ID="<MYTESTCLIENT>"
APS_CLIENT_SECRET="<DKLJSADKNVDSLK15154541215F>"

Be sure to remove the "<" and ">", this stupid error led me down quite the rabbit hole trying to debug. See my stupid stackoverflow post here: 

https://stackoverflow.com/questions/78138283/autodesk-platform-services-access-token

My code is up on github, but it's just a copy of the autodesk code. Feel free to take a peek.
 

What's Next?

I've had people ask, why are you doing this? What's the end goal? Sometimes you don't need an end goal to enjoy the journey. For now, I'm going to keep going with the examples that are up on the APS github. It looks like there is some really cool dashboards that can be created and other exciting stuff. Again, nothing immediately jumps out as me as I need this to improve X/Y workflow, but I have to admit it is cool. 

Another item to research, how much will this cost? APS runs a currency called tokens. How much are tokens? How many tokens are consumed? I've got a lot of questions that I need to dig into to understand a bit more. I have a feeling though, with a name like "tokens" its gonna cost a lot. Maybe it's one of those, if you have to ask, you can't afford it type deals? Let's hope not!

 

RAM to Revit - First Update V1.0.1

The beta release of the RAM to Revit tool has gone well. I have a few people using the tool in practice and have heard some good feedback so far. I am actively trying to maintain this and make it better, so if you have any requests, please reach out. I will try to get your feature added.

Big Update #1 - Calculate X Y and Rotation Function Upgrade

The calculate X Y and rotation function has been greatly improved and does a much better job at trying to guestimate the rotational and offset parameters between your RAM coordinate system and your Revit coordinate system. My error, I had not converted the intersection point of the RAM gridlines into the Revit coordinate system which led to some really bad estimates on X and Y offsets. This has been revised now and should work in a majority of cases.

Update #2 - Mouse Tracking of Coordinate in the Mapping Plane

Should the "Calculate X Y and Rotation" button not do a good job of estimating the X Y and rotation parameters, I have added mouse coordinates in the lower left of the mapping plane. This should allow for easy hand calculations of the X and Y offset parameters should you not be aligned.

Update #3 - Additional Beam Info - RAM Beam #, Camber, LRFD Start and End Reaction

I had a user ask for some additional information the datagrid, RAM beam #, Camber, and beam end shear reactions. Eventually they want to map the start and end reactions into the revit beam for quicker documentation. Side note, I feel sorry for you east coast engineers, sometimes it's just easier to design the simple shear tab connections. 

I am working with this user to see how they like to schedule their end reactions and hope to have a way to write the start and end reaction parameter into the Revit beam soon. More to come on this. The reactions that is recorded is an LFRD factored load reaction that only looks at RAM Steel Beam gravity results. It checks both 1.4DL and 1.2DL + 1.6LL and nothing else. Use with caution.

I also have one user with a weird bug that will not allow them to access the RAM structural API.

I am hoping that this new update will give me a little more insight into why it is not working on their computer. I finally learned how to generate a meaningful error message using the "try" "catch" keywords in C Sharp. Hopefully the exception that is thrown is more insightful than my previous error message.

private void getRAMResults_Click(object sender, RoutedEventArgs e)
{
    if (ramFilePath == null)
    {
        MessageBox.Show($"You must select a RAM Structural model first, .rss", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        return;
    }
    //List<string> storyNames = RAMInfo.GET_STORY_NAMES(ramFilePath);
    try
    {
        List<string> storyNames = RAMInfo.GET_STORY_NAMES(ramFilePath);
        ramFloorComboBox.ItemsSource = storyNames;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"An error occurred: {ex.Message}\n\nLikely errors include:\n\n1. RAM Structural is not installed on your computer\n\n2. Your RAM structural file is corrupt, check for .USR file \n\n3. Clear your working file directory, usually located here C:\\ProgramData\\Bentley\\Engineering\\RAM Structural System\\Working" , "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        return;
    }
}

Section Cut Tool Upgrades

The Section Cut Tool got a big upgrade:
 

  • Ability to plot multiple load steps for a load case that contains multiple directions of loading.
    • Seismic X, Seismic X +e, etc.
    • Currently only supports ASCE 7-16 and ASCE 7-22 seismic loads. If you use this tool and want your specific code included. Leave a comment here or github. Should be a quick enough update.
  • Interactive plots with the data grid below (highlight a row in the datagrid and the corresponding plots will have a gold dot filled in).
  • Tabular data now outputs the length of the section cut.
  • Youtube video for install
    • Hearing yourself on a youtube video is just as bad as one might think it is, but hopefully this will help people get this up and running on their computers.
  • Youtube video for how to use the tool

The code has been updated on github and the install files have been uploaded as well. Give it a spin.

Coding

Coding this involved much more code than what I ever could have imagined. I should now by now that I should take my time estimates to achieve a task and multiply by about 5.

ETABs API - Database Tables, Not As Good As I Once Thought

Database tables seem to be the way the ETABs API is pushing coders to move to access data. This is good and bad from my beginners perspective. The good, most anything is available programatically. The bad, the API response is this garbled, unorganized mess of data. Take for example the section cut results.

I used to be able to call this function to retrieve section cut results before upgrading the tool to pull differing load steps.

This function was nice because it explicitly tells you what it will return. If you happen to throw in a load case with multiple load steps into this function, it will not work for some reason? I was able to get around this by calling the database tables method to return the section cut database table.

            string TableKey3 = "Section Cut Forces - Analysis";
            string[] FieldKeyList = null;
            string GroupName = "All";
            int TableVersion = 1;
            string[] FieldKeysIncluded2 = null;
            int NumRecords = 0;
            string[] TableData2 = null;

            _SapModel.DatabaseTables.GetTableForDisplayArray(TableKey3, ref FieldKeyList, GroupName, ref TableVersion, ref FieldKeysIncluded2, ref NumRecords, ref TableData2);
            //THIS IS THE LIST TO HOLD ALL LOAD STEP RESULTS FOR A SELECTED LOAD CASE WITH STEPS
            listSectionResults = new List<SectionResults>();

            //this is the multiple load steps
            if (FieldKeysIncluded2.Contains("StepNumber"))
            {
                //This list will contain all of the results from one load case with multiplesteps                
                
                List<int> indices = new List<int>();
                // Find indices of "EqAll" in TableData2
                int loadSteps = listBoxLoadSteps.Items.Count;
                indices = SectionCutResults.FindIndices(TableData2, LoadCaseComBox.SelectedItem.ToString());

                //int step = indices.Count() / loadSteps;
                // Grab specific items by index using LINQ
                var specificItems = indices.Where((item, index2) => index2 % loadSteps == 0);
                List<string> OrderedSeismicList = new List<string>();
                OrderedSeismicList = LoadCaseList[index].GetOrderedSeismicDirections();

                //run from 0 to load steps
                for (int i  = 0; i < loadSteps; i++)
                {
                    List<Double> F1loop = new List<double>();
                    List<Double> F2loop = new List<double>();
                    List<Double> F3loop = new List<double>();
                    List<Double> M1loop = new List<double>();
                    List<Double> M2loop = new List<double>();
                    List<Double> M3loop = new List<double>();
                    //IF THIS TABLE GETS REWORKED IN THE FUTURE, THIS WILL NEED TO BE RECODED!!!
                    SectionResults loadCaseResults = new SectionResults();
                    //AREA OF INTEREST

                    //note index is the corresponding loadcase selected in the LoadCaseList
                    //This is Eq X, Eq X e+ etc.
                    loadCaseResults.LoadDirection = OrderedSeismicList[i];
                    //We generatate all of the results for an individual load case, load step in this loop here.
                    foreach (int sectionResult in specificItems)
                    {
                        F1loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 4]));
                        F2loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 5]));
                        F3loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 6]));
                        M1loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 7]));
                        M2loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 8]));
                        M3loop.Add(Convert.ToDouble(TableData2[sectionResult + i * 14 + 9]));
                    }
                    loadCaseResults.F1 = F1loop.ToArray();
                    loadCaseResults.F2 = F2loop.ToArray();
                    loadCaseResults.F3 = F3loop.ToArray();
                    loadCaseResults.M1 = M1loop.ToArray();
                    loadCaseResults.M2 = M2loop.ToArray();
                    loadCaseResults.M3 = M3loop.ToArray();
                    listSectionResults.Add(loadCaseResults);
                }
            }

The problem with this? All the data that is returned is in this massive list/array. I had to write a lot of code to pick apart this massive response, a big bummer from the super clean AnalysisResults.SectionCutAnalysis method used before.

Pro tip, use the view command in visual studio for a variable explorer! So sad I did not know about this until about a week ago. A huge time saver!

The same issue arose with trying to find out what sort of seismic load cases had been generated. The ETABs API developers seem to have made a cognizant decision to move away from specific methods and move towards the database table responses for grabbing all data.

There used to be an autoseismic interface that appeared to work back in the day

but now, these functions do not return anything meaningful. I had to go to database tables to retrieve this info, more unorganized data to sift through and organize myself.

 if (CodeName == "ASCE 7-16")
 {
     string myTableKey = "Load Pattern Definitions - Auto Seismic - ASCE 7-16";
     string[] FieldKeyList = null;
     string GroupName = "";
     int TableVersion = 0;
     string[] FieldsKeysIncluded = null;
     int NumberRecords = 0;
     string[] TableData = null;
     _SapModel.DatabaseTables.GetTableForDisplayArray(myTableKey, ref FieldKeyList, GroupName, ref TableVersion, ref FieldsKeysIncluded, ref NumberRecords, ref TableData);

Another pain point, why do the database tables for auto seismic not correspond to the section cut force analysis tables??? More coding required to dig through all this.

Lastly on the coding side, the plots are now interactive if you click on the row in the datagrid.

The interactive plots with highlighting gold selected rows was achieved through this item in live charts called "mappers". After much coding and interactions with chatgpt, I was able to get a mapper to work with the omitted selected row in the datagrid.

In addition, I attempted to add some code to check if the analysis had already run and skip the tedious rerun if required. I was able to use this function, _SapModel.Analyze.GetCaseStatus(ref NumberItems, ref CaseName, ref status);

to check if the load case had run. Unfortunately though, the section cut definition table is not available if the model is locked and I have a question into CSI regarding this. It seems like you should be able to add section cuts while the model is locked. More on this here.

Uses with the tool

Now that the tool can plot diaphragm shears for code mandated mass eccentricities, I want to run some sample cases to test some of my old design philosophies, for example, due to computational time constraints, I would often design my diaphragm shear DCRs to be a max of 90% to account for the +e/-e mass eccentricities. From my quick tests, this may not have been as conservative as I thought it was.

 

RAM to RevitĀ® - R2R - (part 2)

Link to trial the tool.

Above is the finished beta release R2R tool. It seems to work for large projects and should be a huge time saver and QA/QC tool as compared to manually checking RAM beams to Revit beams.

If you want to be a beta tester for this tool, please either leave a comment/reach out to me. I would be happy to share with you. Please be aware, the tool is still unstable in many conditions, be sure to save a local RAM model and Revit that you do not care about.

How It Works - Screen 1

Screen 1 is where you mostly focus on selection, coordinate system transformation and selection of RAM beams and Revit beams to be mapped. 

The Inputs

Select RAM File

This one is self explanatory, select the .rss file you want to inspect. Be sure that ALL RAM products are closed before doing this, the program will crash if you have RAM open. I need to add some code to catch this error and ask the user to close RAM.

Gather RAM Levels

This button gathers the RAM levels in the project from the selected RAM model. NOTE: the grids will only be imported if you set a max and min in the RAM grid definition.

Select Level

This button will load in the RAM grids into the canvas below and will select the RAM beams at that level to be compared to Revit.

Gather Revit Grids

Button will plot all Revit grids in the Revit canvas. 

Select Revit Beams

Button prompts the user to select revit beams to map, ensure your mapping window for selection is already in your current view. The revit project becomes "locked" when starting up the addin and you are not able to interact with the revit model once you have started up the app. I will work on fixing this in the future. From here, window over any objects you want to map, the selection is filtered down to only select the beams.

With the grids in the mapping window, you can select (2) corresponding grids from the revit model and the ram model and click "Calc X Y and Rotation". This function is rough and not perfect but it attempts to calculate the X Y and Rotation parameter between the RAM and Revit model. Lots of times our RAM models do not align with our Revit models and this function attempts to automate this once manual step.

With the X Y and rotation parameters set, you can save the file path of your .rss file and mapping parameters to .json file. 

Once you are happy with your mapping properties, be sure to hit save so you do not have to do this again. Clicking import brings in these settings and you can mostly skip the import screen save a few buttons:

  • RAM level, select your ram level and beams
  • Selecting your Revit beams.

Sample of the R2R_Json file created:

How it Works - Screen 2

Screen two is pretty simple, you will be greeted with your ram and revit beams being plotted on the canvas in front of you. You can check the RAM or Revit beams on or off as well as control their transparency. Then, click on map the beams and the mapping algorithm will go to town checking all beams in the models. 

A datagrid is populated on the left and discrepancies are highlighted in yellow in the datagrid. You can select the data grid row and it will highlight the selected beam in the mapping panel. The colors are a bit gross right now, but I will work to make the UI a bit more manageable moving forward.

I plan on making a youtube channel to record a video going over all the inputs, typing this all out is tedious and a video would likely be much easier for me and the end user.

The Code

I am pleasantly surprised by how quickly the mapping algorithm works. On the screen at the beginning of the post the algorithm was able to make it through ~1000 revit and ram beams in under 1 second!!! Crazy fast. The algorithm works by taking one RAM beam and then comparing its end point to every Revit beam in the project until the beam is either mapped into the Revit space or is does not find a mate. Let's try to do some quick mental math on the number of calculations performed in this process.

  • 1000 RAM beams, call a distance function on each end point of each Revit beam, assume that a match is found at about the half distance of the Revit Beam list.

  • The first beam in this list would run the distance function 500*2 times = 1000 times, next beam would then 499*2 times = 998 times
  • I thought this was 500!*2, but this seems likely impossible for even a computer to crunch in ~1 second. Google can't even give me an awesome for something over 100! Can someone smarter at math point out where I am wrong? (Edit 2024-01-08, I found my problem, it is the summation of 500*2, not 500!, 125250*2 = 250,500 calculations in ~1 second.)

Developing in C Sharp is starting to become more and more natural, I am really liking the experience now that I am more knowledgeable. At one point, I really liked Python due to it's dynamically typed nature, but type hints in the Revit API are so valuable to know what a function expects to act on. Another fun one, while you are in the visual studio debugger, you can actually make changes to your code while you are debugging and see how your changes affect the code. I had to do this a bunch in my mapping algorithm implementation, ever so slightly tweaking the code as I go. In the code below, tweaking startPoint.Y +/- was really cool while debugging.

As always, ChatGPT is truly a game changer for coding. This project was developed sooooo much quicker becuase of ChatGPT. One small example, in order to make my rows highlight in yellow if the beams between revit and ram did not match seemed like quite a difficult task. XAML does not have a does not equal expression, !=, similiar to that of python/C#, so you have a to write a "Converter" class for XAML and C #. 

I asked chatGPT to do this for me and the code worked perfectly.

Feedback

I have heard a few comments asking how this tool is different from the RAM ISM connection tool. Given that I have not used the RAM ISM connection tool, I cannot answer this. If you have used the connection tool, can you let me know if R2R is the same, does a different task, worse or better the ISM Digital twin product that Bentley seems to offer. 

The Future

Distribution

I am exploring a few different ways to get this tool distributed to a wider mass of structural engineers. If you have experience in dealing with Autodesk, please reach out to me, I would love to pick your brain on this topic.

Work on all levels in the RAM model at once? Expand to check camber, studs, etc.

This would be super cool, maybe there would be a way to check all levels at once with this tool. The tool could be pretty easily expanded to check camber studs, beam end reactions etc. The possibilities are endless, if you have any requests, please let me know. Hopefully this tool allows structural engineers to focus on the more important items in design and less on back checks!.

Fix pan, zoom, other graphics issues, clean up code, focus on DRY coding

Dry coding, do not repeat yourself, was not implemented in this code. I have (3) differing pan zoom and mouse over functions for the RAM and Revit canvas on screen 1, and another pan zoom and mouse over function for screen 2. This leads to lots of repetition and chances for mistakes. I would like to come back to this and make the code more DRY. In addition, the pan function only works if you select an element in the canvas, like a line or text. If you select the big empty white space, the pan function does not work? I need to dig into why. The zoom function in the canvas's are also super whack, with zooming only partially work and zoom into weird spots, not centered on the current mouse position. 

Next steps, I look forward to supporting this product and incorporating any feedback you may have. Again, leave a comment/message me if you want to test the tool out or want additional features. 

For the next part of the site, I want to focus on getting back to structural engineering and less coding. Some examples on non-linear concrete shearwalls, dynamic analysis, rubber isolators and all of that fun stuff. I am excited to get away from coding for a bit.

I also have an itch to dig into machine learning/AI, what is it besides these fun buzz words we hear all the time? I want to explore pytorch/tensorflow and really learn what it means to train a model. How do I create the input nodes for a neural network? I still have no idea how this could relate to structural engineering, but it would be fun to dig and explore the space. 

 

 

SAP2000 API Example

This blog is finally starting to pay off, people are emailing with programming questions and problems. Making programming a little more accessible has always been the goal with the site. Programming can be intimidating to get started!

Foad Kondori emailed me awhile back trying to make a SAP2000 plugin to access frame reactions in SAP2000. I had never written a plugin for SAP2000, but I had written some python code awhile back to access ETABs frame force reactions in Python. I was able to send him my code and he was able to do the rest of the magic to translate the python code to C#. 

The code he wrote is really cool and I appreciate that he allowed me to share this code on github and the blog. Sample shown below retrieving selected frame object type and name

There was one small bug he had in his program and I was able to trouble shoot the culprit, moving the data source out of the for loop did the trick.

His example also provided me some insight on better ways to manage if the SAP/ETABs model has run. 

 bool isModelRunning = _SapModel.GetModelIsLocked();
            if (isModelRunning)
            {

                //get Frame Force

else
            {
                DialogResult result_2 = MessageBox.Show("the model is not run, Do you want Run the model ?"
, "Run Analysis", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

                if (result_2 == DialogResult.Yes)
                {
                    _SapModel.Analyze.RunAnalysis();
                }
            }
        }

These are things I need to implement in the section cutter tool to prevent time consuming re-runs.

Also, I need to dig in and understand why the section cutter ETABs plugin does not work in SAP2000. The APIs between the two program look very similar, but the section cutter plugin does not work in SAP 2000. Foad's example will be a good place to start when trying to troubleshoot.

To CSI, can we improve the SAP OAPi documentation? It only appears to be written for VBA, maybe it could be updated to match that of ETABs, with samples provided for multiple languages?

Feel free to reach out anytime if you are running into programming trouble, I'll try to help if I have the time.

First Previous 1 2 3 4 Next Last

Sidebar

Site Info

  • Latest Comments