Jump to content

Recommended Posts

in a primitive wrangle i have a bunch of line segments as input and i want to use the xyzdist function to find the nearest point on the closest geo. So starting with one line segment each time i want to test against all of the rest segments, so not including its self. The problem is xyzdist(0,@P) means 0 and @P could be the same line. how can i make a condition to avoid that?

xyzdist.hip

Share this post


Link to post
Share on other sites
28 minutes ago, philpappas said:

in a primitive wrangle i have a bunch of line segments as input and i want to use the xyzdist function to find the nearest point on the closest geo. So starting with one line segment each time i want to test against all of the rest segments, so not including its self. The problem is xyzdist(0,@P) means 0 and @P could be the same line. how can i make a condition to avoid that?

xyzdist.hip

I initially tried to do this using the a group expression in the xyzdist, maybe you could still do that

But this works.

xyzdist.hipnc

Share this post


Link to post
Share on other sites
Posted (edited)
34 minutes ago, ColecloughGeorge said:

I initially tried to do this using the a group expression in the xyzdist, maybe you could still do that

But this works.

xyzdist.hipnc

so a for loop is necessary to distinguish the primitive calculating from the rest. thats a bummer i thought you would need to create an array of every primitive except the one currently processing and update that array each time in a primitive wrangle, but i couldnt think of a way to feed the array to the xyzdist function. looks like you can only feed it the node inputs but you cant process that beforehand?

the for loop works though,i'll try the group method you mentioned its probably the simplest way to go keeping everything clean inside a wrangle. i'll post it here if i get it to work. thanks

 

xyzdist.hipnc

Edited by philpappas
  • Like 1

Share this post


Link to post
Share on other sites
29 minutes ago, philpappas said:

so a for loop is necessary to distinguish the primitive calculating from the rest. thats a bummer i thought you would need to create an array of every primitive except the one currently processing and update that array each time in a primitive wrangle, but i couldnt think of a way to feed the array to the xyzdist function. looks like you can only feed it the node inputs but you cant process that beforehand?

the for loop works though,i'll try the group method you mentioned its probably the simplest way to go keeping everything clean inside a wrangle. i'll post it here if i get it to work. thanks

 

xyzdist.hipnc

Yeah unfortunately you have to pass a geometry to xyzdist and to edit a geometry that isnt input 0 in a wrangle, you have to use sops.

I think you can use python to edit two input geometries at once and it has a similar function geometry.nearestPrim()

However I am unsure how to do this.

Share this post


Link to post
Share on other sites

you can exclude the current prim in the xyzdist() function by using groups. i've attached an example.

hth. petz

xyzdist_1.hipnc

  • Like 1

Share this post


Link to post
Share on other sites

nice! i'm trying to execute this for 100.000 prims though, the previous method with the for loop wouldnt finish in my lifetime even if i compiled that which i did. could there be a better method than xyzdist for this operation?

Share this post


Link to post
Share on other sites

yeah looping over all primitives like this, even using groups is going to be very expensive.

One optimization, is giving it a maximum search range (which will speed up the function a lot)
if you have more or less similar expected distances.

float  xyzdist(<geometry>geometry, vector origin, int &prim, vector &uv, float maxdist)

or

float  xyzdist(<geometry>geometry, string primgroup, vector origin, int &prim, vector &uv,float maxdist)

https://www.sidefx.com/docs/houdini/vex/functions/xyzdist.html

generally what I would do is:

int outPr;
float range = chf("range");
vector outUV;

float dist = xyzdist(1, v@P, outPr, outUV, range+0.001);
if(dist > range)
	return;//or continue if in loop

Alternatively, if you are dealing with reaaaly large amounts of geo,
I would suggest just resampling your primitives, saving the primitive number to those new points,
and check the nearest points, instead of using xyzdist() 

 

 

Share this post


Link to post
Share on other sites
On 8.8.2019 at 4:56 PM, philpappas said:

nice! i'm trying to execute this for 100.000 prims though, the previous method with the for loop wouldnt finish in my lifetime even if i compiled that which i did. could there be a better method than xyzdist for this operation?

did you have a look at the file i've attached above? it doesn't use loops but ad hoc groups in the xyzdist() function as well as a max search radius to speed up the search. even though xyzdist() is slower when using groups it shouldn't take ages for 100000 lines ...

Share this post


Link to post
Share on other sites
On 8/11/2019 at 2:39 AM, petz said:

did you have a look at the file i've attached above? it doesn't use loops but ad hoc groups in the xyzdist() function as well as a max search radius to speed up the search. even though xyzdist() is slower when using groups it shouldn't take ages for 100000 lines ...

yes it worked pretty good. there is some lag but not the houdini crash kind of lag!

Share this post


Link to post
Share on other sites
On 8/10/2019 at 2:18 PM, acey195 said:

Alternatively, if you are dealing with reaaaly large amounts of geo,
I would suggest just resampling your primitives

i thought this would be a big no no if i'm already dealing with huge amount of geo. resampling would explode my pc, no?

Share this post


Link to post
Share on other sites
26 minutes ago, philpappas said:

i thought this would be a big no no if i'm already dealing with huge amount of geo. resampling would explode my pc, no?

Well, resampling will indeed increase the usage of RAM, and GPU if you are display it,
but in terms of calculation, using nearpoints() is a way faster (lighter on the CPU) operation than xyzdist()

Also, you could set your resample node's parameter "Create Only Points" (destroying the primitives for the calculation)
which will greatly lower the GPU and a bit of the RAM usage.

It of course matters, what kind of fidelity you need for this, if you really need 0.001m accuracy this method is of course not going to work.
Though, there are certain work-arounds, like measuring the distance to the 2 closest points (instead of 1) and using some geometry math,
to find out where along that edge, lies the actual closest position.

Share this post


Link to post
Share on other sites
22 minutes ago, acey195 said:

what kind of fidelity you need for this

to get some perspective on the amount of geo, i should mention that i'm trying to process an OSM file. if you take a look at the file posted you can see the basis of what i'm trying to do, but multiply that by tens of thousands of city blocks.

Share this post


Link to post
Share on other sites
Posted (edited)
On 12-8-2019 at 3:59 PM, philpappas said:

to get some perspective on the amount of geo, i should mention that i'm trying to process an OSM file. if you take a look at the file posted you can see the basis of what i'm trying to do, but multiply that by tens of thousands of city blocks.

ok, had some time to actually at the file, what I suggested earlier should work for your case, since you are only checking the center of every primitive, once.
So for the final code, I would just do this:

int outPr;
float maxdist = chf("radius");
vector outUV; //to use the range overflow of the xyzdist() you also have to query the primitive and uv for some reason
string grp = sprintf("!%d", @primnum);

f@test = xyzdist(0, grp, @P, outPr, outUV, maxdist + 0.001);

if(@test<maxdist){
    s@near = "close";
    }

with a lot more primitives, its going to be more costly of course, but probably still less than putting it in a loop.
That said, with a very large amount of geometry, you may have to do the calculation in multiple steps,
so not every primitive has to check Every other primitive, but just the ones that are close.

Also, you could add an heuristic, resampling all primitives, adding a center point to all edges and check those first with a nearpoint() expression,
then afterwards, doing the xyzdist() for all the remaining primitives.
That way you could greatly optimize all the plots that have similarly sized buildings next to each other,
as those points will in a lot of cases, nicely line up with the center of the neighbouring primitive in that case,
if you are really afraid about performance.

Edited by acey195

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×