I think I have a headache trying to figure out how to get the range and origin results consistently. For example here are results from the same textElement but accessing the range from different APIs:
Interop - OpenDesignFileForProgram
Range.High.X = 1198162.033
Interop - OpenDesignFile
Range.High.X = 5.77
.NET on Active Design File
CalElementRange.X = 1198162060
.NET on Loaded Design File
Properties examining in the DGN
Origin.X = 5IN 5TN so that looks to match the Range.High.X of the OpenDesignFile in Interop
UOR = 0.000393700787401
With that, I see some correlation between the Interop OpenDesignFileForProgram and NET results, X1000, but i don't understand how i interpret that value to 5.7... Any help to understand this madness is appreciated.
HI Viktor,
Viktor_Kulik said:With that, I see some correlation between the Interop OpenDesignFileForProgram and NET results, X1000
The range should be consistent, because there is only one source of this value: What is stored in DGN in graphical element header, but it looks like APIs report this value in a different way.
...
Element range is always integer (because stored as integer in DGN file), but COM (so VBA and NET/Interop) reports, when possible, values in master units.
Viktor_Kulik said:but i don't understand how i interpret that value to 5.7
I have zero experience with imperial units, and also I do not know what 5IN 5TN means (5 inches and 5<?>), but I think:
Viktor_Kulik said:Any help to understand this madness is appreciated.
It may look like madness, but it is not. The "problem" is that you try to merge/compare different worlds: COM working in MUs, raw access to "work DGN", and NET API (wrapped around C++), working consistently in UORs.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Jan Šlegr said:I have zero experience with imperial units, and also I do not know what 5IN 5TN means
Although I learned imperial units as a kid, I've never come across that format either. It must be a US way of labelling a length. Metric is so much easier.
Jan Šlegr said:Element range is always integer
Every graphic element has a scanrange...
#include <DgnPlatformBaseType.r.h> ScanRange Struct { Int64 xlowlim; Int64 ylowlim; Int64 zlowlim; Int64 xhighlim; Int64 yhighlim; Int64 zhighlim; };
When writing C++ or C#, all coordinates are written in UORs. As Jan comments, VBA attempts to make everything look like user-friendly master units, which fails when you venture outside the comfort zone provided by OpenDesignFile. When attempting to convert a 64-bit integer to a VBA Double, expect inconsistencies.
OpenDesignFile
Double
Regards, Jon Summers LA Solutions
Thank Jan, so believe it or not, TN is actually Tenth, basically at some point someone here thought that fractions were too simple and were likely jealous of the metric system, so they settled with Inches and Tenths of Inches :) I prefer metric system myself as well...
Anyway, your explanation makes sense overall, but I am still struggling to understand how to implement the translation from the stored value to what the user should see (interpreted value).
I'll post back with a more precise comparison later.
Jon Summers said:Metric is so much easier.
100%
Jon Summers said:When writing C++ or C#, all coordinates are written in UORs. As Jan comments, VBA attempts to make everything look like user-friendly master units, which fails when you venture outside the comfort zone provided by OpenDesignFile. When attempting to convert a 64-bit integer to a VBA Double, expect inconsistencies
This makes sense as a concept, but still not clear how you actually convert from UORs to master units.
Viktor_Kulik said:but I am still struggling to understand how to implement the translation from the stored value to what the user should see (interpreted value).
If you are interested in "visual user representation", I recommend to test DoubleFormatter class.
Regards,
I'll take a look at that, and i guess to be clear, i don't need the same visual representation as shown in the properties, with 5IN 5TN and such, just a double as 5.7 would suffice.
Meanwhile:
So let's keep it simple and convert to metric. I have an element with origin of:
X: 0.5M and Y: 0.5M
.NET value provided is:
x: 1198197387
y: 1200802000
The UOR on the model is:
2540
In my oversimplistic understanding of the UORs, its basically a scaling mechanism? So if you want to draw in miles or in centimeters, you can scale the resolution in a way to allow X number of units to be within a single master unit, such as a centimeter or a mile.
With that, resolution of 2540 basically means that there are 2540 units within a single subunit? or unit? (lets assume unit). So the above 0.5M should have a value of 50CM X 2540 which is 127,000.
I realize my UOR understand is way off here, so if you could point me to an article that explains this a bit better, it would help.
Viktor_Kulik said:The UOR on the model is:
What do you mean by "UOR is"? Where this value comes from?
I assume you do not mean URO, but probably UorPerMaster, probably when (quite low) resolution 1000 is set.
Viktor_Kulik said:In my oversimplistic understanding of the UORs, its basically a scaling mechanism?
Not at all. It is one from core model settings (there are several), defining how coordinates are stored. It is not anyhow related to scaling, even when to change UOR setting in existing model leads to change of physical (MU/SU) size, which is usually error.
Viktor_Kulik said:you can scale the resolution in a way to allow X number of units to be within a single master unit, such as a centimeter or a mile.
It is opposite (maybe the main problem is in the used term "scaling", which is wrong in my opinion).
UORs (units of resolution) are basic units (core grid), how coordinates are stored. In other words, this setting (together with resolution and conversion between units and internal system) defines, when coordinates ares stored in DGN file as floating point with double precision numbers, what is a conversion factor.
For example, when there is X-value 1.2 meter (master units), it is not stored as (double)1.2, but as 1.2 x resolution x "units conversion factor". By default (in MicroStation seed files) resolution is 10 000, and the conversion factor is 1 (let's think DGN is based on metric, alternatively unit-less, system internally), so 1.2 meter is stored as (double)12000. It is the value reported by C++ and NET API.
Consequences are:
Viktor_Kulik said:5IN 5TN and such, just a double as 5.7 would suffice.
Simple calculation would be enough, I guess something like value / modelInfo.UorPerMaster shoud return 7.75 (maybe multiplied by resolution).
Viktor_Kulik said:so if you could point me to an article that explains this a bit better
A concept of UORs is typically described in CAD admin articles and blogs (e.g. this one), because for developers, it is usually "just a number", passed from one method to another.
Thanks for clarification Jan. I think "scaling" may be a wrong word to use but the way you explained it aligned mostly with what I was envisioning. So you prompted me to just try a new seed file that's all metric, and the results are as you explained, basically if you take the point data from either CalcRange or GetSnapOrigin and divide it by ModelUOR, you get the actual value you'd expect to see.
But, apparently that's not happening on some of these files for whatever reason. Even if I move the element to 0,0,0 in the model, then attempt to read that in .net it gives me:
DPoint3d xyz="1198147387,1200752000,0"
Which in my understanding should be a zero no matter the resolution.
Then I decided to create new model and move the content there, but still reporting these large numbers. Then I changed the model resolution and units to metric, but STILL reporting numbers that don't seem to correlate to anything. At this point I am thinking it's something corrupted in the drawing or maybe left over in some settings from the past? What's weird is that the GUI is able to report the right info. So it gives me hope that there's still some way of decoding that.
But, in the end, as long as the positioning is correct in relationship to other elements, I'm probably going to just go with these large numbers for my purpose.
Viktor_Kulik said:if you take the point data from either CalcRange or GetSnapOrigin and divide it by ModelUOR
When MU:SU are metric, yes.
Viktor_Kulik said:But, apparently that's not happening on some of these files for whatever reason.
It's hard to say without sharing the file, because I can imagine more reasons why range is not as expected:
Viktor_Kulik said:I'm probably going to just go with these large numbers for my purpose.
There are only a few "typical"reasons, why to access element range information:
Viktor_Kulik said:This makes sense as a concept, but still not clear how you actually convert from UORs to master units.
Attachment and ModelReference objects have a property called UORsPerMasterUnit, so X master units = X*UORsPerMasterUnit UORs.
It could pay off nicely to make it a function to take a load off your brain and that of others ever looking at your code:
Function UORsFromMU(x_MU as double, oModel as ModelReference) as double UORsFromMU = x_MU * oModel.UORsPerMasterUnit End Function Function MUsFromUOR(x_UOR as double, oModel as ModelReference) as double MUsFromUOR = x_UOR / oModel.UORsPerMasterUnit End Function
I suppose it's fair to say I'm assuming that you're working in VBA which I realize after the fact is probably not a safe assumption, but there you go. At least this sort of thing would be the route I would take to make sure everything is more reliable.