Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by QuantumCD · Sep 25, 2013 at 03:36 PM · c#dataalgorithm

Find Nearby Points

I'm having trouble efficiently getting nearby points within a certain distance. I have a large collection of points (Vector3's) which tops out at around 500,000. I've found some solutions for finding the nearest point (nearest-neighbor search) with a KD-Tree. However, I cannot find anything that has range-searching. Are there any other methods I could use for this, or will I need to roll my own KD-Tree with range-searching? The "problem" is sort of like this: for every point, get points within a range of the point, and modify those points. The abstract idea has to do with changing colors and other properties based on proximity to other points.

Comment
Add comment · Show 7
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image robertbu · Sep 25, 2013 at 04:09 PM 0
Share

I've never implemented one my self, but Octree's have been suggested for similar Questons on list in the past:

http://en.wikipedia.org/wiki/Octree

I just searched to see if Octree's were in any way superior to $$anonymous$$D-Trees and bumped into this reference:

http://cstheory.stackexchange.com/questions/8470/why-would-one-ever-use-an-octree-over-a-kd-tree

$$anonymous$$ Eppstein's answer suggest that an Octree might be superior for what you are trying to do.

avatar image QuantumCD · Sep 25, 2013 at 04:17 PM 0
Share

Yes, I read that. I don't know though... I have never seen an Octree used for range-based finding. Do note that I'm not trying to find the nearest-neighbor, but nearest-neighbor*s* within a given radius (probably fairly small--around 1.5 or so).

avatar image robertbu · Sep 25, 2013 at 04:25 PM 0
Share

I've never used an Octree or a $$anonymous$$D-Tree, so you are likely in a better position to judge the algorithms. But what I got from a quick read was that with an Octree, it is easy to find a node or leaf in the tree that contains all possible nearby points as defined by your criteria. That is it is efficient at partitioning your search set. And that it might be, on average, more efficient to search a bucket for a set of points rather than repeatedly walk a tree.

avatar image QuantumCD · Sep 25, 2013 at 04:31 PM 0
Share

@robertbu - Yeah, this isn't my first foray into the phantasmagorical world of spatial indexing... I understand where you're co$$anonymous$$g from though, with Octrees. I'm by no mean an expert at this though. :P

Perhaps I will look into Octrees... I just don't know if it'll work for my particular problem. I'm not looking for all the nearby points, collectively. I'm looking for all the points around a given point... so searching inside a node might not work, right?

Take point A and point B. I'm trying to find all points within 1.5f units of A. B falls within that range, and it's also inside the same node/leaf as A. However, C is within 1.5f units from A, but it isn't in the same node.

avatar image robertbu · Sep 25, 2013 at 04:48 PM 0
Share

The way I see it is that you walk the tree and identify any bucket/leaf that is within your search area. Assu$$anonymous$$g your bucket size is more than 2 * dist, then your best case scenario is a single bucket, and your worst is four buckets.

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Jamora · Sep 25, 2013 at 06:26 PM

The most efficient solution I can think of is just plain sort the list of vectors by their sqrMagnitude to the point being compared to. Sorting is relatively fast; the fastest comparison sorts (e.g. MergeSort or QuickSort) can be done in O( n*log(n) ). If you save the sqrMagnitudes, finding the set of points within a given range is a matter of selecting an appropriate amount of elements from the beginning with a sqrMagnitude smaller than searchedDistance^2. Using binary search, this can be done in O( log(n) ) time.

However, with a large dataset even the fastest methods will take a while, so if you're looking for performance, you should first and foremost figure out a way to make your dataset smaller.

EDIT:

Some kind of a data structure would be preferable if searches are frequent. The sorting would have to be redone on each Vector3 whose nearest neighbors must be found.

Originally I was thinking of a spherical radius, which was the vibe I got from the question. However, if a cube works too, it is even simpler to find the Vectors:

 List allVectors of Vector3
 List neighbors of Vector3
 Vector3 origin
 float distance
 
 foreach (vector in allVectors){
     if (CheckDistance(origin.x, vector.x) && 
         CheckDistance(origin.y, vector.y) &&
         CheckDistance(origin.z, vector.z)){
             neighbors.Add(vector);
     }
 }
 
 bool CheckDistance(float origin, float otherPoint){
     return (otherPoint > origin-distance && 
             otherPoint < origin+distance)
 }

If a spherical distance is required, this method could be used to pre-compute suitable vectors to minimize the work done when sorting.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image QuantumCD · Sep 25, 2013 at 06:32 PM 0
Share

Yeah, definitely agree with that last point. :P

I actually am working with dynamic meshes that can top out at several million vertices if left unoptimized, so I had to work that out first. I cut down the vertices by about 90%, so a few $$anonymous$$utes would be a plausible time to do these operations, I think.

Right now, the most expensive operation I'm doing on the vertices is a raycast. Take 12$$anonymous$$ vertices on a single mesh that needs this operation. Square that. 144 million raycasts--i.e. not feasible. Now take 12$$anonymous$$ * n where n is the number of nearby points to a given vertex. Due to the density of the mesh's geometry, n is about 10 on average. So, 120$$anonymous$$ raycasts is way, way, way faster and allows me to do some extra work with the raycasts.

avatar image QuantumCD · Sep 25, 2013 at 06:34 PM 0
Share

I will see about sorting them in a Dictionary with your approach when I get to my dev machine later. I'll report back when I have something (hopefully good news). Thanks for the insight. Perhaps I can even run the sort in another thread and cheat a little bit. ;)

avatar image QuantumCD · Sep 25, 2013 at 07:23 PM 0
Share

Hmm, just thinking about this, how would I efficiently get the nearest points though? Wouldn't I have to re-sort the entire list based on the point?

avatar image QuantumCD · Sep 25, 2013 at 07:55 PM 0
Share

Good thinking! I didn't think about precomputing to cut back on necessary sorting.

I don't know if a square will work, but I'll definitely try it.

avatar image
1

Answer by EvilWarren · Sep 26, 2013 at 05:14 PM

Interesting problem. You could throw a cube down your kd tree and see what it catches. Been a while since I used a kd tree but I remember passing a line segment down the tree to catch triangle intersections so I think throwing a cube down there should be relatively fast. You could use a sphere as well but the calculations at each node might bog you down. You can just test the sphere intersection at leaf nodes. It would probably work out quicker if you're working with small distances. I haven't checked this code for correctness but hopefully it will give you the general idea and of course I have no idea how you implemented your tree so adapt as needed

 List<Vector3> GetVerticesInRange(Vector3 point, float range, KdTreeNode node)
     {
         List<Vector3> vertices = new List<Vector3>();
         if(node.isLeafNode())
         {
             foreach(Vector3 v in node.verticeList)
             {
                 float xd = point.x - v.x;
                 float yd = point.y - v.y;
                 float zd = point.z - v.z;
                 
                 if((xd*xd + yd*yd + zd*zd) <= range*range )
                 {
                     vertices.Add(v);
                 }
             }
         
             return vertices;    
          }
         
         if(point[axis]- range <= median)
         {
             vertices.AddRange(GetVerticesInRange(point, range, node.left));
         }
         
         if(point[axis]+ range > median)
         {
             vertices.AddRange(GetVerticesInRange(point, range, node.right));
         }
         
         return vertices;
     }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

A fast triangle triangle intersection algorithm for unity? 4 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Number of scripts per Object. Optimization question. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges