I need to get the location where two curves intersect with geometry nodes
3 Answers
There are probably other (and better) ways to do this, but an easy one would be to convert the curves to meshes with a small radius and then use the Mesh Boolean node set to Intersect to get the intersection.
The below example places a sphere at the calculated intersection point by averaging the min and max outputs from the Bounding Box node.
-
2
Variant 1
This variant produces the desired result with a few nodes (Of course, this is in the eye of the beholder, but for this task there are relatively few):
At the beginning I create a
Mesh Line
, so that I can easily extrude the resulting edge on the Z-axis with the nodeExtrude
.Then I use the node
Raycast
and simply transfer the Hit Position to another object.
Variant 2
This variant is pretty hare-brained, mathematical and a bit messy, but it works perfectly.
Basically, here I just translated a VEX code I once wrote for Houdini into Geometry Nodes.
It looks terrible, and I don't have much overview there myself anymore, but just put it into a node group, then you don't have to see it ;-).
/// <summary>
/// Get the coordinates of the intersection point of two lines.
/// </summary>
/// <param name="a1">A point on the first line.</param>
/// <param name="a2">Another point on the first line.</param>
/// <param name="b1">A point on the second line.</param>
/// <param name="b2">Another point on the second line.</param>
/// <returns>Returns false there is no solution.</returns>
function int lineLineIntersection(
vector a1; vector a2;
vector b1; vector b2;
export vector i
) {
float intersection, multiplier;
intersection = (b2.x - b1.x) * (a2.y - a1.y) - (b2.y - b1.y) * (a2.x - a1.x);
// No solution: lines are not intersecting
if (intersection == 0) {
return 0;
}
multiplier = ((a1.x - b1.x) * (a2.y - a1.y) - (a1.y - b1.y) * (a2.x - a1.x)) / intersection;
i = set(
b1.x + (b2.x - b1.x) * multiplier,
b1.y + (b2.y - b1.y) * multiplier
);
return 1;
}
Note, these variants work fine, but only on the X/Y plane, so two-dimensional.
Variant 3
Only meant as a quick update (see comments) ...more detailed description follows:
-
$\begingroup$ I would describe Variant 1 as using "quite a lot" of nodes, rather than a few. Variant 2 I'd probably go with "loads". I suspect it feels like less when you have been using geometry nodes more/longer as you clearly have, but when you said "a few nodes" I was expecting something quite different. Lovely solutions mind you! $\endgroup$– BenCommented May 20, 2022 at 10:48
-
$\begingroup$ @Ben The pure logic uses only four nodes (
Extrude Mesh
,Raycast
,Integer
andTransfer Attributes
), the rest is really just mesh and depends on what exactly you want to do and how you set it up. But, yes, you are right ;-) ...this is unfortunately a general disadvantage with geometry nodes: Everything that is not available as a node has to be created by yourself. So 10 nodes appear quickly as "few nodes" in such sepcific cases. $\endgroup$– quellenform ♦Commented May 20, 2022 at 10:56 -
$\begingroup$ Perhaps in a while I'll be able to reorient my perceptions so that that also feels like a few nodes. Hopefully, because right now I find everything I try and make takes at least three to four times as many operations and steps as I think it will. $\endgroup$– BenCommented May 20, 2022 at 10:59
-
$\begingroup$ @quellenform I'm really impressed with both variants. But in both cases they work with simple inputs, would it be possible to use fields? I'm trying to find the intersection of each edge of a mesh with its next indexed edge. I would really apreciate any help here. $\endgroup$ Commented Aug 25, 2022 at 12:02
-
$\begingroup$ @JuanManuelLynch I'm sorry, I don't have much time and I'm very busy at the moment, but I quickly added a third variant that might help you (please forgive me that I can't go into more detail at the moment, but I'll do it later). $\endgroup$– quellenform ♦Commented Aug 25, 2022 at 18:30
Quellenform's solution looks like an established mathematical solution, so there probably isn't room for optimization, unless you can get away with resigning from some checks, or Blender gives you a shortcut with some nodes that have complex inner workings; for example I use just two nodes: map range + compare with 0 εpsilon 1, instead of minimum, maximum, greater than, less than and boolean or. And I get very high numbers for parallel lines instead of NaN, so it works too. However, in the end the setup the setup turned out obese, so it's only good in a specific situation when you have one line aligned with one axis (which is incidentally the case for LeoHernandez from Discord whose problem pointed me to this thread) or if you want to see the reasoning behind the calculation and perhaps add some optimizations based on a deeper understanding on what's going on…
If you rotate the lines so one is horizontal/vertical:
It becomes trivial to find if the lines are parallel, simply check the 2nd line length when squashed on the axis the first is parallel with:
Length 0 = parallel.
To check if line segments cross, you need to see if the 2nd rotated line crosses the axis, and does so within the first line. To further make the problem easier, offset these lines to position the first at an axis:
Now calculate the ratio of x to y (the slope). Since you know how far away you're from the axis (that's just the coordinate on the other axis), you can multiply it by the ratio to see how far away the sampled point (one of ends of the line segment) is from the intersection with the axis:
In order to check if the line segments intersect, as opposed to just infinite mathematical lines, you need to check if the 2nd line indeed goes through the axis, and also pass the Y coord through a map range, where "from" values are the first segment's vertices, and "to" values are such that it's easy to check if you went outside that range (remember to disable clamping):
All that's left is to reverse the offset and the rotation (Invert option) and perhaps put it all in a single node tree. I decided to resign from temporary geometry changes and to put the calculations into a separate tree, with the same interface as quellenform's variant 3:
Designing vertical trees is my passion.
This works only for 2D lines, but since you're rotating anyway, you could rotate more - you could rotate all 4 points so that the first line is aligned with X, and then rotate all 4 points around x (which wouldn't affect the first line so you can skip two nodes if you don't use the set position approach) to make sure the 2nd line is not aligned with XZ plane. Now again you can disregard Z, except once you find the intersection point, you need to see if it's close enough to 0 on Z axis to your liking (for exact match, εpsilon=0).
-
1$\begingroup$ +1 I love your craziness and this answer (as well as your vertical node trees)! $\endgroup$– quellenform ♦Commented Jan 12, 2023 at 19:19