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.
How to calculate distance across a surface?
chris_houser
Member Posts: 6 ✭
My goal is to write a script to add a hexagonal pattern of hexagonal tiles across a series of adjacent surfaces. However, I'm new to Featurescript so at an early stage.
Where I'm stuck at the moment is trying to convert from realworld distances to the "2d unitless parameterspace" used as parameters to evFaceTangentPlanes. I'd like the user to be able to specify something like 5mm, and for the script to calculate how much to add to the x or y of the 2d vector to move 5mm across the surface.
I figured out how to get the length along the curve of each perimeter edge, which is close:
You can see my attempts so far here. My document is a bit messy, both the geometry and the code. Let me know if cleaning it up would help answer my question. I started with the Surface Pattern script, and most of it's still there. I'm successfully creating an almosthexagonal pattern of spheres, but still depending on Surface Pattern's parameters of number of repeats in the u and v directions, rather than being able to specify the distance between them.
Where I'm stuck at the moment is trying to convert from realworld distances to the "2d unitless parameterspace" used as parameters to evFaceTangentPlanes. I'd like the user to be able to specify something like 5mm, and for the script to calculate how much to add to the x or y of the 2d vector to move 5mm across the surface.
I figured out how to get the length along the curve of each perimeter edge, which is close:
for (var q in evaluateQuery(context, qEdgeAdjacent(definition.Face, EntityType.EDGE))) { println("len: " ~ evLength(context, {"entities": q}));
In particular, evLength's distance along a curve is like what I want but not along the edges, rather along the curve of the surface in whatever direction evFaceTangentPlanes's coordinates run.
I tried to figure out how to get a coordinate system from the surface, figuring I could then use coordSystem conversion functions like toWorld and fromWorld, but I don't know if that would work, and could figure out how to get a coordinate system anyway.
Anyone have any ideas?
I tried to figure out how to get a coordinate system from the surface, figuring I could then use coordSystem conversion functions like toWorld and fromWorld, but I don't know if that would work, and could figure out how to get a coordinate system anyway.
Anyone have any ideas?
You can see my attempts so far here. My document is a bit messy, both the geometry and the code. Let me know if cleaning it up would help answer my question. I started with the Surface Pattern script, and most of it's still there. I'm successfully creating an almosthexagonal pattern of spheres, but still depending on Surface Pattern's parameters of number of repeats in the u and v directions, rather than being able to specify the distance between them.
Tagged:
0
Best Answer

chris_houser Posts: 6 ✭The ratio of surfaceparameter distance to 3d world distance is not constant across the surface. Moreover, I don't think it's geometrically possible to get exactly what I want.
However, I may be able to get close enough. I don't plan to actually apply hexagonal tiles to any spheres. This is what I have so far:/** * Estimate the 3d location of a point across a surface in a given vector direction. * @param face {Query} : Surface across which distances will be estimated * @param start3d {Vector} : 3d world coordinate of the starting point from which to step (should be a point on the surface) * @param start2d {Vector} : 2d unitless vector corresponding to the start3d point * @param step2d {Vector} : 2d unitless vector, a direction and an initial guess for the final return step * @param target_distance : desired length from starting point to the point this function will return. */ function surfaceStep(context is Context, face is Query, start3d is Vector, start2d is Vector, step2d is Vector, target_distance) { var next_tan_plane; for (var i = 0; i < 3; i += 1) { next_tan_plane = evFaceTangentPlane(context, { "face" : face, "parameter" : step2d + start2d }); debug(context, start3d, next_tan_plane.origin); var step_norm = norm( start3d  next_tan_plane.origin ); println("dist: " ~ step_norm ~ " target: " ~ target_distance); step2d = target_distance * step2d / step_norm; } return {"step2d": step2d, "target": next_tan_plane}; }
That could be cleaned up quite a bit: maybe more convenient parameters and using a target epsilon (distance error) rather than hardcoding 3 loop iterations. Anyway, I'm using that to compute step sizes near the origin on the surface, and using those step sizes to lay out a pattern of spheres along the surface. Here's that script applied to a few surfaces:
2
Answers
Is this only meant to be for planar surfaces?
 Some surfaces don't intersect a plane going through their origin.
 When they do intersect, it may not cover the full range from 0 to 1 of the surface parameter space.
So I think my next attempt will be to use evFaceTangentPlane to get realworld 3d coords of two points: the origin, and a point very close in the 'u' direction, like vector(0.1, 0). Finding the distance between those points should let me calibrate the surface parameter dimension to realworld distance. Do that again for the 'v' direction, and maybe that'll be enough info to space things properly. ...assuming the correlation is constant across the surface. :PHowever, I may be able to get close enough. I don't plan to actually apply hexagonal tiles to any spheres. This is what I have so far:
That could be cleaned up quite a bit: maybe more convenient parameters and using a target epsilon (distance error) rather than hardcoding 3 loop iterations. Anyway, I'm using that to compute step sizes near the origin on the surface, and using those step sizes to lay out a pattern of spheres along the surface. Here's that script applied to a few surfaces: