Hi people,
i´m trying to implement this code in a dynamic plugin, but i don´t know really how it works...
http://www.openprocessing.org/visuals/?visualID=8009
If anybody has a moment to check it would be great, this is my first attempt to make a plugin.
Here there is a realted thread.
intersect-between-several-circles
Thanks in advance,
ari.
Hi,
i think i´ve got it, but it returns 2 solutions even if one of the points is into the circle.
Any idea?
ari
It seems that all the people is on Hollydays ?¿
Haven't looked at your code, but i guess it creates the formula of the line based on the 2 points you pass to the algorithm.
And of course this line (almost) always has 2 intersections with the circle.
I guess if you only want the intersection that lies between these 2 points, take the solution(x,y) where solution(x) is between P1(x) and P2(x) and solution(y) is between P1(y) and P2(y).
Hi ft, thanks a lot for your response.
this is the code, i´ve just implemented the processing one.
Any help would be great.
Ari.
#region usings using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "CircleLineIntersect", Category = "Value", Help = "Basic template with one value in/out", Tags = "")] #endregion PluginInfo public class ValueCircleLineIntersectNode : IPluginEvaluate { #region fields & pins [Input("CircleCenter")] ISpread<Vector2D> center; [Input("CircleRadius", DefaultValue = 1.0)] ISpread<double> cr; [Input("Line1")] ISpread<Vector2D> L1; [Input("Line2")] ISpread<Vector2D> L2; [Output("Intersection 1 ")] ISpread<Vector2D> FIntersection1; [Output("Intersection 2 ")] ISpread<Vector2D> FIntersection2; [Output("Number of Solutions")] ISpread<int> FSolutionCount; [Import()] ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersection1.SliceCount = SpreadMax; FIntersection2.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for (int i = 0; i < SpreadMax; i++) { Vector2D s1; Vector2D s2; FSolutionCount[i] = CircleLineIntersection(center[i], cr[i], L1[i], L2[i] , out s1, out s2); FIntersection1[i] = s1; FIntersection2[i] = s2; } //FLogger.Log(LogType.Debug, "Logging to Renderer (TTY)"); } private int CircleLineIntersection (Vector2D center, double cr, Vector2D L1 , Vector2D L2, out Vector2D p1, out Vector2D p2) { p1 = new Vector2D(); p2 = new Vector2D(); double dx = L2.x - L1.x; double dy = L2.y - L1.y; double a = dx * dx + dy * dy; double b = 2 * (dx * (L1.x - center.x) + dy * (L1.y - center.y)); double c = L1.x * L1.x + L1.y * L1.y + center.x * center.x + center.y * center.y - 2 * (center.x * L1.x + center.y * L1.y)-(cr * cr); double bb4ac = b * b - 4 * a * c; double mu1 = (-b + Math.Sqrt(bb4ac)) / (2*a); double mu2 = (-b - Math.Sqrt(bb4ac)) / (2*a); double i1x = L1.x + mu1*(dx); double i1y = L1.y + mu1*(dy); double i2x = L1.x + mu2*(dx); double i2y = L1.y + mu2*(dy); double dist1 = Math.Sqrt((L1.x-center.x)*(L1.x-center.x)+(L1.y-center.y)*(L1.y-center.y)); double dist2 = Math.Sqrt((L2.x-center.x)*(L2.x-center.x)+(L2.y-center.y)*(L2.y-center.y)); double dist3 = Math.Sqrt((L2.x-L1.x)*(L2.x-L1.x)+(L2.y-L1.y)*(L2.y-L1.y)); double dist4 = Math.Sqrt((p1.x-i1x)*(p1.x-i1x)+(p1.y-i1y)*(p1.y-i1y)); double dist5 = Math.Sqrt((p1.x-i2x)*(p1.x-i2x)+(p1.y-i2y)*(p1.y-i2y)); if (bb4ac < 0) { // Not intersecting return 0; } if (bb4ac > 0) { //2 solutions p1.x = i1x; p1.y = i1y; p2.x = i2x; p2.y = i2y; return 2; } if (bb4ac == 0) { //1 solution tangent p1.x = i1x; p1.y = i1y; return 1; } // Figure out which point is closer to the circle if (dist1 < dist2 ) { //&& cr >= dist2 p1.x = L2.x; p1.y = L2.y; return 1; } if (dist1>dist2 ) { p1.x = L1.x; p1.y = L1.y; return 1; } if (dist4 < dist3 || dist5 < dist3) { //2 solutions p1.x = i1x; p1.y = i1y; p2.x = i2x; p2.y = i2y; return 2; } else { return 0; } } } }
Hi people,
i´ve made some changes and it works more or less, but when the points are outside the circle, the plugin shows 2 values instead of 0.
if anyone has time to look at it, it would be great.
Thanks,
Ari.
#region usings using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "CircleLineIntersect", Category = "Value", Help = "Basic template with one value in/out", Tags = "")] #endregion PluginInfo public class ValueCircleLineIntersectNode : IPluginEvaluate { #region fields & pins [Input("CircleCenter")] ISpread<Vector2D> center; [Input("CircleRadius", DefaultValue = 1.0)] ISpread<double> cr; [Input("Line1")] ISpread<Vector2D> L1; [Input("Line2")] ISpread<Vector2D> L2; [Output("Intersection 1 ")] ISpread<Vector2D> FIntersection1; [Output("Intersection 2 ")] ISpread<Vector2D> FIntersection2; [Output("Number of Solutions")] ISpread<int> FSolutionCount; [Import()] ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersection1.SliceCount = SpreadMax; FIntersection2.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for (int i = 0; i < SpreadMax; i++) { Vector2D s1; Vector2D s2; FSolutionCount[i] = CircleLineIntersection(center[i], cr[i], L1[i], L2[i] , out s1, out s2); FIntersection1[i] = s1; FIntersection2[i] = s2; } } private int CircleLineIntersection (Vector2D center, double cr, Vector2D L1 , Vector2D L2, out Vector2D p1, out Vector2D p2) { p1 = new Vector2D(); p2 = new Vector2D(); double dx = L2.x - L1.x; double dy = L2.y - L1.y; double a = dx * dx + dy * dy; double b = 2 * (dx * (L1.x - center.x) + dy * (L1.y - center.y)); double c = L1.x * L1.x + L1.y * L1.y + center.x * center.x + center.y * center.y - 2 * (center.x * L1.x + center.y * L1.y)-(cr * cr); double bb4ac = b * b - 4 * a * c; double mu1 = (-b + Math.Sqrt(bb4ac)) / (2*a); double mu2 = (-b - Math.Sqrt(bb4ac)) / (2*a); double i1x = L1.x + mu1*(dx); double i1y = L1.y + mu1*(dy); double i2x = L1.x + mu2*(dx); double i2y = L1.y + mu2*(dy); double dist1 = Math.Sqrt((L1.x-center.x)*(L1.x-center.x)+(L1.y-center.y)*(L1.y-center.y)); double dist2 = Math.Sqrt((L2.x-center.x)*(L2.x-center.x)+(L2.y-center.y)*(L2.y-center.y)); if (bb4ac < 0) // Not intersecting (bb4ac < 0) { return 0; } if (bb4ac==0 ) //1 solution tangent (bb4ac == 0) { p1.x = i1x; p1.y = i1y; return 1; } if ( (dist1>=cr & dist2>=cr )) //2 solutions (dist1>=cr & dist2>=cr) { p1.x = i1x; p1.y = i1y; p2.x = i2x; p2.y = i2y; return 2; } //else {return 0;} if ( (dist1>=cr & dist2<=cr)) //1 solution { p1.x = i2x; p1.y = i2y; return 1; } if ( (dist1<=cr & dist2>=cr)) //1 solution { p1.x = i1x; p1.y = i1y; return 1; } { return 0; } } }}
Finally i found the solution for the 5 cases, in a "finite line - circle intersection".
Thanks ft for the hint.
Ari.
Is there any way to do this spreadable???
Hi Ari,
Its been a while since you posed the question but I recently started looking for the answer too. Andy McW and I went over the plugin to try and figure out a spreadable method and we got a very workable if not perfect solution.
The patch explains why but it ain't bad.
Here's the code if you wanna peak:
using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "IntersectCircles", Category = "2d", Help = "Basic template with one value in/out", Tags = "")] #endregion PluginInfo public class C2dIntersectCirclesNode : IPluginEvaluate { #region fields & pins [Input("Centers")] ISpread<Vector2D> FCenters; [Input("Radii", DefaultValue = 1.0)] ISpread<double> FRadii; [Output("Intersections")] ISpread<Vector2D> FIntersections; [Output("Number of Solutions")] ISpread<int> FSolutionCount; [Import()] ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersections.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for(int i = 0; i < FIntersections.SliceCount; i++) { FIntersections.RemoveAt(i); } for (int i = 0; i < SpreadMax; i++) { for (int j = i + 1; j < SpreadMax; j++) { Vector2D s1; Vector2D s2; FSolutionCount[i] = CircleIntersection(FCenters[i], FRadii[i], FCenters[j], FRadii[j], out s1, out s2); FIntersections.Add(s1); FIntersections.Add(s2); } } } private int CircleIntersection (Vector2D c1, double c1r, Vector2D c2, double c2r, out Vector2D p1, out Vector2D p2) { p1 = new Vector2D(); p2 = new Vector2D(); //Calculate distance between centres of circle double d = !(c1 - c2); double m = c1r + c2r; double n = c1r - c2r; if (n < 0) n = n * -1; //No solns if ( d > m ) return 0; //Circle are contained within each other if ( d < n ) return 0; //Circles are the same if ( d == 0 && c1r == c2r ) return 0; //Solve for a double a = ( c1r * c1r - c2r * c2r + d * d ) / (2 * d); //Solve for h double h = Math.Sqrt( c1r * c1r - a * a ); //Calculate point p, where the line through the circle intersection points crosses the line between the circle centers. Vector2D p; p.x = c1.x + ( a / d ) * ( c2.x -c1.x ); p.y = c1.y + ( a / d ) * ( c2.y -c1.y ); //1 soln , circles are touching if ( d == c1r + c2r ) { p1 = p; return 1; } //2solns p1.x = p.x + ( h / d ) * ( c2.y - c1.y ); p1.y = p.y - ( h / d ) * ( c2.x - c1.x ); p2.x = p.x - ( h / d ) * ( c2.y - c1.y ); p2.y = p.y + ( h / d ) * ( c2.x - c1.x ); return 2; } } }
Hope its still helpful,
Hadasi
Grande Hadasi!
i´ll try to use the same method to Circle-Line and Line-Line intersections.
could i share it as a contribution?
Thanks a lot.
Ari.
Be our guest!
The idea came from Elias'sConnectAll">ConnectAll)) dynamic plug-in he did for his tutorial. In it he showed how multiple vectors can be made to analyse each other (the "for j = i+1" bit).
Most of the credit goes to Andy McWilliams and your good self, though, co-opted the ideas into a something usable and lovely.
Looking forward to the lines version!
Hayd
you should replace these lines
for(int i = 0; i < FIntersections.SliceCount; i++) { FIntersections.RemoveAt(i); }
with this
FIntersections.Clear();
it's easier to read and has a better run time, as removing them one by one will trigger a shift of all remaining slices each time you remove one slice.
Danke Elias.
Hi Elias,
.Clear method wasn't recognised.
whaaat? :p
ok, then replace it with a
FIntersections.SliceCount = 0;
Hey guys,
i´m trying to make the multiple finite lines version,
but i don´t know how to feed the plugin with a spread of points instead of 4 points with individual inputs.
Any tip?
thanks.
#region usings using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "MultipleLinesIntersect", Category = "Value", Help = "2 lines intersect", Tags = "")] //Source: //http://paulbourke.net/geometry/lineline2d/ //Credits: //Lasal 2011 #endregion PluginInfo public class Value2LinesIntersectNode : IPluginEvaluate { #region fields & pins // Could it be possible to use a spread of points? [Input("P1")] ISpread<Vector2D> P1; [Input("P2")] ISpread<Vector2D> P2; [Input("P3")] ISpread<Vector2D> P3; [Input("P4")] ISpread<Vector2D> P4; [Output("Intersection")] ISpread<Vector2D> FIntersection; [Output("Number of Solutions")] ISpread<int> FSolutionCount; [Import()] ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersection.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for(int i = 0; i < FIntersection.SliceCount; i++) { FIntersection.RemoveAt(i); } for (int i = 0; i < SpreadMax; i++) { for (int j = i + 1; j < SpreadMax; j++) { Vector2D s1; Vector2D s2; //How to use 10 variables? P1[j], P2[j], P3[j], P4[j] FSolutionCount[i] = LinesIntersection( P1[i], P2[i], P3[i], P4[i], out s1, out s2); FIntersection.Add(s1); FIntersection.Add(s2); } } } private int LinesIntersection ( Vector2D P1 , Vector2D P2, Vector2D P3 , Vector2D P4, out Vector2D so1, out Vector2D so2) { so1 = new Vector2D(); so2 = new Vector2D(); // Denominator for ua and ub are the same, so store this calculation double d = (P4.y - P3.y) * (P2.x - P1.x) - (P4.x - P3.x) * (P2.y - P1.y); //n_a and n_b are calculated as seperate values for readability double n_a = (P4.x - P3.x) * (P1.y - P3.y) - (P4.y - P3.y) * (P1.x - P3.x); double n_b = (P2.x - P1.x) * (P1.y - P2.y) - (P2.y - P1.y) * (P1.x - P2.x); // Calculate the intermediate fractional point that the lines potentially intersect. double ua = n_a / d; double ub = n_b / d; double SX = P1.x + (ua * (P2.x - P1.x)); double SY = P1.y + (ua * (P2.y - P1.y)); if (d == 0) // Parallel lines. { return 0; } if (SX < P1.x & SX < P2.x | SY < P1.y & SY < P2.y | SX > P1.x & SX > P2.x | SY > P1.y & SY > P2.y ) // No finite lines intersecting, delete this for infinite lines Intersection. { return 0; } // than 0 the lines would need to be longer to intersect. if (ua >= 0d && ua <= 1d && ub >= 0d && ub <= 1d) { so1.x = SX; so1.y = SY; return 1; } { return 0; } } }}
I think Input 1 could be "line start(vector2D)" and Input 2 "line end(vector2D)."
Then you can compare the spread of lines
j = i + 1; line1[i]; line2[j];
(Pardon my lack of correct formatting, and the fact I may be wrong)
Hayd
PS thanks Elias
Bam:
#region usings using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "MultipleLinesIntersect", Category = "Value", Help = "2 lines intersect", Tags = "")] //Source: //http://paulbourke.net/geometry/lineline2d/ //Credits: //Lasal 2011 #endregion PluginInfo public class Value2LinesIntersectNode : IPluginEvaluate { #region fields & pins // Could it be possible to use a spread of points? [Input("Line Start")] ISpread<Vector2D> P1; [Input("Line End")] ISpread<Vector2D> P2; [Output("Intersection")] ISpread<Vector2D> FIntersection; [Output("Number of Solutions")] ISpread<int> FSolutionCount; [Import()] ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersection.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for(int i = 0; i < FIntersection.SliceCount; i++) { FIntersection.SliceCount = 0; } for (int i = 0; i < SpreadMax; i++) { for (int j = i + 1; j < SpreadMax; j++) { Vector2D s1; Vector2D s2; //How to use 10 variables? P1[j], P2[j], P3[j], P4[j] FSolutionCount[i] = LinesIntersection( P1[i], P2[i], P1[j], P2[j], out s1, out s2); FIntersection.Add(s1); FIntersection.Add(s2); } } } private int LinesIntersection ( Vector2D P1 , Vector2D P2, Vector2D P3 , Vector2D P4, out Vector2D so1, out Vector2D so2) { so1 = new Vector2D(); so2 = new Vector2D(); // Denominator for ua and ub are the same, so store this calculation double d = (P4.y - P3.y) * (P2.x - P1.x) - (P4.x - P3.x) * (P2.y - P1.y); //n_a and n_b are calculated as seperate values for readability double n_a = (P4.x - P3.x) * (P1.y - P3.y) - (P4.y - P3.y) * (P1.x - P3.x); double n_b = (P2.x - P1.x) * (P1.y - P2.y) - (P2.y - P1.y) * (P1.x - P2.x); // Calculate the intermediate fractional point that the lines potentially intersect. double ua = n_a / d; double ub = n_b / d; double SX = P1.x + (ua * (P2.x - P1.x)); double SY = P1.y + (ua * (P2.y - P1.y)); if (d == 0) // Parallel lines. { return 0; } if (SX < P1.x & SX < P2.x | SY < P1.y & SY < P2.y | SX > P1.x & SX > P2.x | SY > P1.y & SY > P2.y ) // No finite lines intersecting, delete this for infinite lines Intersection. { return 0; } // than 0 the lines would need to be longer to intersect. if (ua >= 0d && ua <= 1d && ub >= 0d && ub <= 1d) { so1.x = SX; so1.y = SY; return 1; } { return 0; } } }}
Gets a little upset if I try to setup a line one axis going along a zero co-ordinates, but seems okay otherwise. Any ideas how to avoid that?
Hayd
you had an error in calculation of n_b, and parallel worked but your demo patch didn't display it properly.
i simplified code and patch a little, seems to work fine now.
nice one
Sweet as a nut. Cheers Elias.
wow,
i was missing only one day and look at this ;)
Thanks Hadasi and Elias
Taking advance of the situation...
I´m cleaning up the Multiple circle intersection plugin and, it shows variables even when there isn´t any solution.
Anyone knows how to return false (nil) when there isn´t any intersection?
It seems that the behaviour is different than the multiple lines intersect.
Thanks
#region usings using System; using System.ComponentModel.Composition; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "IntersectCircles", Category = "2d", Help = "Basic template with one value in/out", Tags = "")] #endregion PluginInfo public class C2dIntersectCirclesNode : IPluginEvaluate { #region fields & pins [Input("Centers")] ISpread<Vector2D> FCenters; [Input("Radius", DefaultValue = 1.0)] ISpread<double> FRadii; [Output("Intersection")] ISpread<Vector2D> FIntersections; [Output("Number of Solutions")] ISpread<int> FSolutionCount; // [Import()] // ILogger FLogger; #endregion fields & pins //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FIntersections.SliceCount = SpreadMax; FSolutionCount.SliceCount = SpreadMax; for(int i = 0; i < FSolutionCount.SliceCount; i++) { FIntersections.SliceCount = 0; } for (int i = 0; i < SpreadMax; i++) { for (int j = i + 1; j < SpreadMax; j++) { Vector2D s1; Vector2D s2; if ( CircleIntersection(FCenters[i], FRadii[i], FCenters[j], FRadii[j], out s1, out s2)) FIntersections.Add(s1); FIntersections.Add(s2); } } } private bool CircleIntersection (Vector2D c1, double c1r, Vector2D c2, double c2r, out Vector2D p1, out Vector2D p2) { p1 = new Vector2D(); p2 = new Vector2D(); //Calculate distance between centres of circle double d = !(c1 - c2); double m = c1r + c2r; double n = c1r - c2r; if (n < 0) n = n * -1; //Solve for a double a = ( c1r * c1r - c2r * c2r + d * d ) / (2 * d); //Solve for h double h = Math.Sqrt( c1r * c1r - a * a ); //Calculate point p, where the line through the circle intersection points crosses the line between the circle centers. Vector2D p; p.x = c1.x + ( a / d ) * ( c2.x -c1.x ); p.y = c1.y + ( a / d ) * ( c2.y -c1.y ); //No solns //Circle are contained within each other //Circles are the same if ( d > m || d < n || d == 0 && c1r == c2r) { return false; } //1 soln , circles are touching if ( d == c1r + c2r ) { p1 = p; { return true; } } //2solns p1.x = p.x + ( h / d ) * ( c2.y - c1.y ); p1.y = p.y - ( h / d ) * ( c2.x - c1.x ); p2.x = p.x - ( h / d ) * ( c2.y - c1.y ); p2.y = p.y + ( h / d ) * ( c2.x - c1.x ); return true; { return false; } } } }
anonymous user login
~3h ago
~1d ago
~2d ago
~2d ago
~2d ago
~2d ago
~2d ago
~2d ago
~3d ago
~3d ago