1
$\begingroup$

In the image below, there is a solution that seems to work. The question is: Do you know of a better solution in terms of performance?

spline group ID

$\endgroup$
6
  • $\begingroup$ Fill curve is slow. Can be optimized by (theoretically) using "Group ID" or (practically) temporary instancing, but here the whole idea is to use it on all geometry at once... Can you upload a .blend file saved in latest stable version of Blender? I think this one is saved in βeta or αlpha... $\endgroup$ Commented Feb 10 at 9:53
  • $\begingroup$ The file should be latest portable 4.3.2, but redownloaded B3D and resaved again. Have some idea, but not sure yet it will lead to some result and about the final performance... i.imgur.com/CjJDJfr.jpeg $\endgroup$ Commented Feb 10 at 10:29
  • $\begingroup$ ...gotta leave it for now, any help appreciated i.imgur.com/29P175p.jpeg $\endgroup$ Commented Feb 10 at 10:58
  • $\begingroup$ Sorry, it was my fault, I updated 4.3.0 to 4.3.2. In your latest comment in the screenshot what is the arrow marking? $\endgroup$ Commented Feb 10 at 11:45
  • $\begingroup$ it marks the wrong ID (work to do) i.imgur.com/TL1M7c1.jpeg $\endgroup$ Commented Feb 10 at 14:12

2 Answers 2

1
$\begingroup$

This solution is slower than fill curve. Well I didn't compare with fill curve + extrude + normal check, but probably slower anyway. I can produce an artificial case in which this solution is faster, for example 10 nested circles with 20k resolution each (check the file at the end) will make my solution an order of magnitude faster.

You can check previous revision of this answer to see the thought process.

Imgur mirror (SE image hosting has problems)

  1. Prepare Geometry - convert splines to Targets. A Target is just a spline converted to mesh and extruded up, so that raycasting can be used on it. Normals are recalculated to point outside. Also convert vertical edge of this geometry to points, which will hold ray data, therefore the points are called Rays.

  2. Make Gun Range - The Targets together are called Target Level, because each set of mesh islands has to be duplicated for each spline ("geometry explosion") because it is going to be duplicated in a moment, with each duplicate on a separate $z$ position (separate floor or level). All duplicates together I call Gun Range.

  3. Extended Raycast - contains the Raycast node and some basic logic and data reading/storing that otherwise would repeat later in the node tree (inside the repeat zone), but also to keep the setup as simple as possible. Notice how they rays are moved vertically, each having its own level.

  4. Kill Targets - imagine going horizontally through a (somehow closed) sinusoid, you would keep entering/leaving the same spline. However you only need to hit each curve once to determine if it's inside it, based on normal. So once the Target is hit, it is removed from the Gun Range, making sure you don't hit it again. This also makes the repeat zone very manageable, because you know you can hit at most each spline once, so the number of iterations can be set to the number of splines. The deletion also means you don't need the classic offset by normal scaled by 0.001 to not hit the same Target again.

  5. Delete Geometry - remove Ray data that never hit anything, because it doesn't contain any useful information.

  6. Store first_exit for your Rays, the calculated value is -1 if there wasn't an exit.

  7. Repeat Zone: do raycasts, notice this time position isn't passed - that's because Extended Raycast moves the point to the hit position internally. Kill Targets works the same way, storing first_exit makes sure to store it only on points that haven't yet encountered an exit, and rays that missed are separated and moved to Escaped Rays as finished job; thanks to this, most iterations do nothing, because for most inputs all rays will escape on like 10% of first iterations, and then the rest of iterations does nothing (consider adding 3 switches with a check of domain size to further optimize).

  8. If you unmute the Subtract node, then Join Geometry also has to be unmuted because then theoretically some rays could hit all splines and so they may have not "escaped" yet.

  9. Map Values does the usual geonodes logic to read calculated data from rays and move it onto the splines.

The algorithm assumes all splines are cyclic, so remove non-cyclic splines before using it.

Prepare Geometry

Imgur mirror

I'm renaming spline_i to ray_i just for readability, so you're less likely to confuse a context in which they are evaluated. In general it should be easier to understand the setup if you keep in mind those two, as well as level and Index in spline context, are equivalent.

Make Gun Range

Imgur mirror

Notice the spline_i = level removal, because a ray starting at a particular spline doesn't want to hit its own spline. Remember what I said about Subtract and Join Geometry nodes? Actually you can unmute just the former, or unmute both and subtract $2$ instead.

Extended Raycast

Imgur mirror

⚠ The Position input has to be set to default to a position in the numbers panel!

Also, the exit_count could just be a boolean exit_count_odd, and instead of adding to it, you could just "boolean math: NOT" it, as that's all what we care about if the number of exits is even or odd.

Kill Targets

Imgur mirror

Pink Mapping: For those rays that missed, move them (the points) to $<0, 0, ray_i>$. You kind of don't have to do that, you could use "Transform Geometry" to scale to 0 on $xy$ axes, and then translate down by $0.5$ for the same effect.

Brown mapping: rays that didn't miss: move them like in the pink mapping, but also set $x$ to Target (spline_i) that was hit.

This way for missed rays you can remove entire level, and for other rays only the Target that was hit.

Map Values

Imgur mirror

Delete rays that have an even number of exits, because the first exit of those is not the filling pair. For the rest again use the mapping by position, setting their position to their ray_i. Then for each spline, check if it has a ray-point sitting on it's spline index. If not, it's an outside spline of a filling pair, or a spline without a pair. In such case just set the ID to the index. Otherwise it's an internal spline of a filling pair, so read from the found point the first_exit which holds the index of the external spline of the pair.

Imgur mirror

Blend 4.3.2

Some further ideas

Maybe you can remove entire level on finding the first exit curve. This should make raycasting much faster, but then you would need to do more mapping magic at the end to figure out the evenness. I kind of hinted in the first revision how that could be done...

$\endgroup$
14
  • $\begingroup$ thanks, from first glance your RC idea seems to me similar to what am trying to do right now, instead extruding and checking the face normals I determine if curve is cw or ccw ant reverse cw to ccw, then use simple 2d curve offset (dot normal scale) inside (here 50cm for visualization), then RC outside and set curve line instances to is hit start points + deleting the one that hit red faces. then sampling nearest the original ID from endpoints. Final timing seems to grow though... i.imgur.com/8aAoQmo.jpeg $\endgroup$ Commented Feb 10 at 14:33
  • $\begingroup$ That's what I'm doing with accumulating signed angle, cw or ccw. It won't work for a "8" shape spline however $\endgroup$ Commented Feb 10 at 16:20
  • $\begingroup$ Regarding O(n²) complexity, just figured it can be done in a single repeat zone using the good ol' geometry explosion trick, as you can copy all raycasting setups (extrusions) to simultaneously parse each spline. I'll play with it tomorrow. $\endgroup$ Commented Feb 10 at 23:59
  • $\begingroup$ Using explosion in another stuff (mentioned in another question you can maybe remember) far better than repeat zone, but even with this the timing gets probably over the fill curve algorhitm. Here it is 2.3ms, no RC just connecting vertices and refining selection instance line points i.imgur.com/ZHtctj6.jpeg $\endgroup$ Commented Feb 11 at 7:05
  • $\begingroup$ was thinking about this lately today, try to imagine this situation i.imgur.com/8TFzDGw.jpeg, it can be even more dense, raycast is not reliable, I dont know if there is some fast algorhitm (no rc but pure math) to check for each explosion spline ID what curves(points) are inside curve polygon - going opposite way... $\endgroup$ Commented Feb 11 at 17:49
1
$\begingroup$

This approach uses duplicate elements node:

  • 1.seperate one point on each spline, that will represent raycasting ID
  • 2.set spline Z positions to their ID and extrude
  • 3.duplicate points by spline domain size and set their Z to duplicate index
  • 4.now you have iterations separated by their Z position and you can start raycast

My english is limited so below are the images explaining the process + two blend files. One purged and second with extra nodes to help visualize and understand the process. I have not tested this in many scenarios yet, but it seems to work OK and the timing in large counts is 10-30x faster comparing to the fill curve method.

thanks Markus with help on this!

result: result

engine: engine

data for final logic: final logic

file with extra nodes:

file purged:

$\endgroup$
6
  • $\begingroup$ resulting ID in this method is ascendig row, however there are gaps, for sorting this out I am using this way: i.imgur.com/BXCbJWA.jpeg - as still learnig - is there any better method? $\endgroup$ Commented Feb 13 at 9:56
  • $\begingroup$ Hi, great job! I'm still analyzing it. For one, I don't know if the way you check spline winding/normal is clever, but for some reason it didn't occur to me you could just check the leftmost point. However, the logic is unnecessarily complicated: once you have the leftmost point, just read its normal and separate x. If it's positive, the normal is OK (points outside). No need to do the cross/dot. As for performance, I'm still analyzing the tree, it's hard because a lot of nodes are renamed so I need to inspect the .blend. I wonder how you calculate the 'evenness' without a repeat zone. $\endgroup$ Commented Feb 13 at 16:48
  • $\begingroup$ Oh and sorting is O(n log n) while summing (my way) is O(n), so in principle my way should be faster, but I wouldn't bet on it being actually the case. In the end of the day that part of the setup probably doesn't matter performance-wise. $\endgroup$ Commented Feb 13 at 16:49
  • $\begingroup$ Thanks Markus, with the levels we have same approach, but as I said before, when you know the curves are not crossing (entire curve is inside or outside) you are ok with using of any point of the curve for checking agains one extruded ID, that way you cannot hit any other curve except the one against you checking. Eveness is yellow node layers /2 fraction ceil. I am self thought so most ways using can be amateur naive strange approaches. Happy when you point this out - thanks! Try to duplicate the splines 10x or 30x the performance difference is significant. $\endgroup$ Commented Feb 13 at 17:23
  • $\begingroup$ the CW checking idea is coming from this en.wikipedia.org/wiki/Curve_orientation the most right or most left point has to be convex - or am I wrong? Do not understand to this O(n log n) while summing (my way) is O(n). $\endgroup$ Commented Feb 13 at 17:27

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.