Find by location?

I have no idea how this would be done, but if someone could shed some magical light upon me I’d be very grateful. Essentially in Maya I’d like to pass in a xyz coordinate and a threshold, and return any object(s) in that location… without looking up the location of every object in the scene.

Can it be done? Just a pipe dream?

In max there is a relatively fast function to test if an object intersects another. Assuming there is an equivalent fn in maya, just create an axis-aligned bounding box centered on your desired point, and “for obj in geometry do (if intersects targetbox obj do addtoselection obj” or something along those lines. This does touch all the objects in the scene, but again is relatively fast in Max depending on the density of the scene.

the first method i can thin of is something like…

  1. define the worldspace that you want to use as your “area”…
  2. list all transforms in the scene
  3. loop throught them and query their world space
  4. compare against your worlds space position
  5. if its within the threshold then add it to a list array…then select at the end

may not be brilliant but something like that

hope that helps

[QUOTE=andylt1;5122]the first method i can thin of is something like…

  1. define the worldspace that you want to use as your “area”…
  2. list all transforms in the scene
  3. loop throught them and query their world space
  4. compare against your worlds space position
  5. if its within the threshold then add it to a list array…then select at the end

may not be brilliant but something like that

hope that helps[/QUOTE]

Yeah thanks but that’s the one I know how to do already, and it’s very slow… I guess if it’s a small scene it’ll work fine though.

I’m pretty sure there is something in the API that will detect collisions on an object. Sort of like Wessau said, you could probably get your coordinate, then create a sphere at that coordinate with your threshold as the radius, and detect collisions on that sphere.

I’ll be damned if I can remember what it was in the API, but I know it exists. Good luck!

Either way I don’t think you can get away from running that check against each object.
There is no way to approximate which objects you should query without actually queering them.
You could to a hierarchical query (think along the lines of a quadtree algorithm). You check the top of the branch first if it hits then you check the children and so on, but this assumes the children haven’t moved from their parent so it won’t really be valid in a lot of cases!

What wessau posted is actually very fast, in max of course. However the “intersect” function works off of a bounding box (not sure about the maya equivalent). You could pass a radius instead and it would allow for tighter spacing between objects.

for object in geometry where a distance or length function of (x,y,z) and objects in geometry <= (threshold value) do something that I want.

Also not sure how fast this would actually be, but you could use a plane and find which faces intersect point x,y,z. All you have to do is check for collisions at the faces which intersect point x,y,z, at the given threshold to filter out the unwanted objects, but I’m just spit balling here…

hey could you give us an example a something… cause I think I mite know of a script that you could use to solve this… though it might need a little fixing to be used for your exact situation.

If you need to very many of those find by location tests, you can use your favourite space partitioning algorithm to speed them up.
Octrees are relatively easy to understand and implement. I used them for a skin weight blurring script for example. (for every selected vertex, find all vertices within X range)
These basically cut up space into many sectors and assign objects to each sector. This happens once after every scene change.
Then you can quickly search through the resulting data structure and find objects by sector.

It’s quite a bit of scripting/coding work so it’s only worth it of you need to do very many of these searches.

www.gamedev.net has quite a few articles on octrees and spatial hashing

The reason I asked about this was simply to find a mirrored joint on the opposite side of the YZ plane, so for that, checking location of the <150 joints isn’t such a big deal and will probably go pretty fast.

Basically I was hoping there was some handy shortcut I didn’t know about(that I could use for other things as well), but it sounds like no matter what the solution, it’ll take some time to write. I’ve got some leads now if I want to go that route, so thanks.

I was thinking about this today, and just thought of a strategy that might work for larger scenes. I have never used maya before, but this is just a generic idea:

On scene load, build a hash table containing every object with it’s x position as the index. do the same for y, and for z. A total of three tables, one for each axis.

Get all items in the x table based on the location and threshold. if you find any results, add them to a list of result objects.

Now you only have to find the objects within this list that also contain similar Y ranges, and again for z.

You only need to test one axis at a time, since the result needs to be within the threshold for all 3 to return true. the hashtables Might be kind of large if you have a ton of objects, but hash tables should be pretty good at this. looping through arrays like this would make your computer cry.

Essentially you’re just narrowing the search using fast hashtables instead of just iterating through every object in the scene.

I did this kinda thing before when trying to match verts across meshes with different topology.

MEL is incredibly bad at handling large arrays, hence most people tend to offload this approach to the API - oftentimes the computer would hang simply because Maya takes forever scanning through the arrays.

I agree with Jeremy’s suggestion. You can add the objects to hashtables and taking it a step further, per index entry. You could store all the floats, sorted, with separating commas, for example:

x_var[270] will contain 270.5[mesh300], 270.53[mesh10020], 270.8[mesh090]

y_var[300] will contain 300.1[mesh300], 300.12[mesh20]

z_var[102] will contain 200.0[mesh20], 200.1[mesh300]

You can split these combined strings using tokenize (",") or MEL’s stringToStringArray command, then parse through this new list for the closest match you require. So here I can find “mesh300” quite quickly.

Your array length will be a little smaller, though each index will be longer and you might get perhaps a slight speed increase searching for your object.

-w