Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- Be respectful, on topic and if you see a problem, Flag it.
If you would like to contact our Community Manager personally, feel free to send a private message or an email.
distance measurement speed tips?
EvanReese
Member, Mentor Posts: 2,188 ✭✭✭✭✭
I'm working on a feature that involves possibly thousands of evDistance() calls, which are by far the most intensive part of the whole thing. Does anyone have any tips for me here on how to speed up? One side of the measurement will always be a point vector, but the other side should be able to be any object. Some thoughts below.
- If it were always 2 vectors I could probably just do it with math. Maybe I can at least check if it's 2 vectors and do that as an alternative.
- One way to reduce the number of calls. could be to only make ones that are within a given distance so I'm not measuring ones farther away. But I'm not sure how to do that without measuring it first if there is a clever way.
Any ideas?
- If it were always 2 vectors I could probably just do it with math. Maybe I can at least check if it's 2 vectors and do that as an alternative.
- One way to reduce the number of calls. could be to only make ones that are within a given distance so I'm not measuring ones farther away. But I'm not sure how to do that without measuring it first if there is a clever way.
Any ideas?
Evan Reese
0
Best Answers
-
Jacob_Corder Member Posts: 137 PROyep.
for evDistance, calling the @ version eliminates building structures like lines,vectors and other types.
var dist = @evDistance(context, {"side0" : something,"side1" : somethingElse,"arcLengthParameterization":false});evaluate functions in parasolid do execute using multi core parallelism. It is faster to measure many points and an object than to measure each point and the same object multiple times. This is the same for evEdgeTangentLine(s) and evFaceTangentPlane(s)
for vectors this is MUCH faster than using norm. Norm is crazy slow/** * Much faster than norm as this removes the units which is 5x faster */ function pointDistance(vec0, vec1) returns ValueWithUnits { if (vec0[0] is ValueWithUnits) vec0 = removeVectorUnitsReturnArray3D(vec0); if (vec1[0] is ValueWithUnits) vec1 = removeVectorUnitsReturnArray3D(vec1); return point3DDistanceFast(vec0, vec1) * meter;<br>} function point3DDistanceFast(vec0 , vec1 ) { vec0[0] -= vec1[0]; vec0[1] -= vec1[1]; vec0[2] -= vec1[2]; return @sqrt(vec0[0] * vec0[0] + vec0[1] * vec0[1] + vec0[2] * vec0[2]); // returns a point with units if vec0 and vec1 have units. returns number if no units } function removeVectorUnitsReturnArray3D(vec) returns array { return [vec[0].value, vec[1].value, vec[2].value]; }
also, if you are doing for loops like this for( var i =0; i<size(something);i+=1)
it is faster to do this
var ct = size(something);
for(var i=0;i<ct;i+=1)
as size(something) is evaluated at every return to the top of the loop. I have seen this add a second to a huge for loop.
The last thing to do is profile when its done to find the bottlenecks. Once you find them, and they are in the standard library, ctrl+click the function to see what is taking so long.
2 -
Jacob_Corder Member Posts: 137 PRO@evDistance and evDistance both work with the same stuff. evDistance just converts points to vectors with units, parameters for faces to a vector..
just look at evDistance in the standard library how many conversion checks it goes through.
For @evDistance, the distance is a number in meters.
The returned point (.sides[x].point) is an array of 3 numbers . Converting to vector with units is simple but if not necessary then its wasted time(this takes about 20% of the regen time to convert to a vector with units).
The parameter from a face (.sides[x].parameter) is also an array of 2 elements, not a vector like evDistance returns
If you need the distance between each point and each object, then in your case it seems you need to run them in a loop, Thousands of points to a face just really cannot be optimized without being able to parallel execute the measurement(which I know you can do in solidworks. Hint hint onshape)
to check the impact of evDistance vs @evDistance. Run a profile on your part, then ctrl+click the evDistance function and see how long it takes to execute the extra stuff in the standard library. In my case right now @evDistance takes 350 ms, but the rest of the stuff is taking 170 ms so total is 520ms. you can see how much time is saved there using @evDistance
0
Answers
for evDistance, calling the @ version eliminates building structures like lines,vectors and other types.
var dist = @evDistance(context, {
for vectors this is MUCH faster than using norm. Norm is crazy slow
also, if you are doing for loops like this for( var i =0; i<size(something);i+=1)
it is faster to do this
var ct = size(something);
for(var i=0;i<ct;i+=1)
as size(something) is evaluated at every return to the top of the loop. I have seen this add a second to a huge for loop.
The last thing to do is profile when its done to find the bottlenecks. Once you find them, and they are in the standard library, ctrl+click the function to see what is taking so long.
it is faster to do this
var ct = size(something);
for(var i=0;i<ct;i+=1)
as size(something) is evaluated at every return to the top of the loop. I have seen this add a second to a huge for loop.
I guess this isn't too surprising, but I have to wonder why FeatureScript isn't a little smarter to know that size(something) isn't changing in the body of the loop. But then I suppose you could just as easily have a condition where i<foo and you actually want foo to be able to change during iterations of the loop.
Is this true in other languages? Somehow I would assume a while loop would reevaluate the entire condition each time, but a for loop seems more like something where you pick your beginning and end and iteration, and go.
just look at evDistance in the standard library how many conversion checks it goes through.
For @evDistance, the distance is a number in meters.
The returned point (.sides[x].point) is an array of 3 numbers . Converting to vector with units is simple but if not necessary then its wasted time(this takes about 20% of the regen time to convert to a vector with units).
The parameter from a face (.sides[x].parameter) is also an array of 2 elements, not a vector like evDistance returns
If you need the distance between each point and each object, then in your case it seems you need to run them in a loop, Thousands of points to a face just really cannot be optimized without being able to parallel execute the measurement(which I know you can do in solidworks. Hint hint onshape)
to check the impact of evDistance vs @evDistance. Run a profile on your part, then ctrl+click the evDistance function and see how long it takes to execute the extra stuff in the standard library. In my case right now @evDistance takes 350 ms, but the rest of the stuff is taking 170 ms so total is 520ms. you can see how much time is saved there using @evDistance
@evFaceTangentPlanes is like 5x faster than evFaceTangentPlanes (or something silly like that)
for any trig that you need to do, stripping the vector and valuewithUnits makes it SOOOOO much faster.