Well, it is cumbersome to locate the problem without any hints, just by looking at code. Please construct a simple situation like a segment (0,0) to (10,0) and a circle at (5,0) with radius 1, and write out the resulting values of eDistAtoB (should be 10) and t (should be 5). Further dt should be 1, and hence tMdt == 4 and tAdt == 6. Obviously, this should result in true for both tM and tA. Where does this break, and with which values?
 Home
 » Viewing Profile: Reputation: haegarr
haegarr
Member Since 10 Oct 2005Offline Last Active Oct 04 2015 08:29 AM
About Me
Community Stats
 Group Crossbones+
 Active Posts 3,916
 Profile Views 10,677
 Submitted Links 0
 Member Title Member
 Age Age Unknown
 Birthday Birthday Unknown

Gender
Male
#5228730 Intersection between circle and line segment
Posted by haegarr on 13 May 2015  03:22 AM
#5228726 Intersection between circle and line segment
Posted by haegarr on 13 May 2015  03:01 AM
Oh, I've not considered that vector d is normalized. So t (or tdt or t+dt) need not range from 0 to 1 but from 0 to eDistAtoB … I think at least ...
So try
var tM = tMdt >= 0 && tMdt <= eDistAtoB, tA = tAdt >= 0 && tAdt <= eDistAtoB;
instead of
var tM = tMdt >= 0 && tMdt <= 1, tA = tAdt >= 0 && tAdt <= 1;
if(t >= 0 && t <= eDistAtoB){
if(t >= 0 && t <= 1){
#5228719 Intersection between circle and line segment
Posted by haegarr on 13 May 2015  01:59 AM
a) In case of 2 intersections: You need to check both intersections not together but on their own. Also there is an error with the condition on tAdt!
b) In case of 1 intersection: You should use t >= 0 && t <= 1 instead of t > 0 && t < 1
#5228713 Intersection between circle and line segment
Posted by haegarr on 13 May 2015  01:32 AM
Okay now i restructured my code
Well, now you use a totally different method of computation: Before it was checking for the point on the segment that is closest to the circle's origin, now you use the implicit circle formula to check for identical points on the line. That is a replacement, not a restructuring!
The originally used method has the advantage that the distance of the intersection along the segment was computed, and that is good to judge whether the intersection is inside or outside the segment's range. The now use method does not compute that distance anywhere. So ...
a) you go back and use the original method, together with the 2 conditions I've posted above; I would suggest this way (in assumption that the original method works well for lines),
or
b) you check whether the computed intersections(s) are between the endpoints of the segment. For this you can use the projection method, too.
#5228703 Intersection between circle and line segment
Posted by haegarr on 13 May 2015  12:53 AM
AFAIS the method used above computes the relative projected length of the difference vector (between the line segment's start and the center of the circle) and the line segment. The result denotes the distance to the point on the segment and closest to the circle, and it is stored in variable t.
a) If there is just 1 intersection than t need to be between 0 and 1, because the closest point is also the intersection point.
b) If there are 2 intersections then the intersections are at distances tdt and t+dt. Any of these need to be in the range [0,1] to be valid.
#5228150 Get the distance of an intersection
Posted by haegarr on 09 May 2015  12:48 PM
Yes because basically the ray object just holds two points [...]
The ray has a member named "origin" and a member named "direction". While the type of the origin is a point vector, the type of the direction is, well, a direction vector. A direction vector is the difference vector from one point to another and, usually also normalized in its length. Defining a ray that way is natural since a ray is a directed infinite long line. The formula I've chosen to describe the ray in one of the posts above reflects this, i.e.
r( k ) = v_{1} + k * v_{2}
where v_{1} is the origin (a point) and v_{2} is the direction. Since a point plus a difference vector gives again a point, the formula describes well an infinite set of points that together give the ray.
[…] and i didn't want to create another object
Since your line segments use the same class, they naturally fall into the same interpretation. It is not good practice to interpret the same class in different ways just at will. As you can see here, all my posts have been written under the assumption that the variable names stand for what commonly is understood for them, and foremost that they are interpreted uniformly.
[…] because now my segments are not displayed the way i wanted them to be, aren't they?
To solve this, if your line segment goes from point p_{1} to point p_{2}, and you want to use the ray class to store it, then convert (p_{1},p_{2}) into a ray like so:
seg.origin.x = p1.x;
seg.origin.y = p1.y;
If, on the other hand, you want to store a segment as 2 points, then make another class with members e.g. from and to, and adapt the computations accordingly to the substitution
v_{3} := p_{1}
v_{4} := p_{2}  p_{1}
resp. in code
x3 = seg.from.x;
y3 = seg.from.y;
x4 = seg.to.x  seg.from.x;
y4 = seg.to.y  seg.from.y;
#5228099 Get the distance of an intersection
Posted by haegarr on 09 May 2015  07:20 AM
The intersection test works fine, but your javascript is wrong at two places (or: your naming of variables does not match their usage):
1.) You draw the segment as point to point, but the naming suggests that it has an origin and a direction.
2.) The same is true for the ray.
Hence try the following replacement:
var draw = function(){ for(var i = 0; i < segments.length; i++){ var seg = segments[i]; ctx.beginPath(); ctx.moveTo(seg.origin.x, seg.origin.y); ctx.lineTo(seg.origin.x + seg.direction.x, seg.origin.y + seg.direction.y); // <<<< LOOK HERE ctx.stroke(); } }; canvas.onmousemove = function(event){ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); ctx.beginPath(); ctx.arc(event.pageX, event.pageY, 4, 0, 2 * Math.PI, false); ctx.fillStyle = '#FF0000'; ctx.fill(); draw(); var r = new ray(new vec(center_x,center_y), new vec(event.pageX  center_x, event.pageY  center_y)); // <<<< LOOK HERE var ret = r.intersect(); if(ret != null){ var hitPoint = r.origin.add(r.direction.multFloat(ret)); // <<<< ((compute this only if ret != null)) ctx.moveTo(center_x, center_y); ctx.lineTo(hitPoint.x, hitPoint.y); ctx.stroke(); } };
#5228091 Get the distance of an intersection
Posted by haegarr on 09 May 2015  06:46 AM
Sorry, I've made a mistake in replacing the indices when copying from paper to the web editor. The mistake was below "Otherwise…".
Please try
var k = (y4 * (x3  x1) + x4 * (y3  y1)) / det; var n = (y2 * (x3  x1) + x2 * (y3  y1)) / det;
instead of what I told before.
That's clearly the reason why I always mention "please check twice" ;)
#5228075 Get the distance of an intersection
Posted by haegarr on 09 May 2015  04:55 AM
Instead using an arbitrary number as limit, using a value that could not occur in a valid solution would be better. That could (if supported by the language) a nil / null / void, in case of a floating point result also NaN, and so on. In your case you want to return only positive distances, so an invalid value would also be any negative number. Hence
something like
var finalLen = 1.0; ... if (finalLen<0  length < finalLen) finalLen = length; ...
would be a working solution that does not use arbitrary numbers, and hence would be better practice.
#5228061 Get the distance of an intersection
Posted by haegarr on 09 May 2015  02:20 AM
Is my code correct?
I haven't investigated the math in that code snippet. However ...
* The selection is definitely not correct, since it does not necessarily return the minimal distance of all intersections in front of the ray origin. Instead, it returns the distance of the last intersection found in that direction. You need to assign the computed length to the finalLen if and only if the new distance is less than any previously assigned value.
* Where comes the initial "5000" from? Is it an arbitrary value you have picked, or it is correctly chosen as a limit where actually computed lengths definitely fall below? If the latter, have you considered that a length is computed (and hence to be compared) as square norm, so that a limit need to be squared, too?
#5227968 "simple" equation confusion (a  b = c)
Posted by haegarr on 08 May 2015  09:50 AM
B = C  A (5 = 10  15)
and NOT
B = A  C
Err, why NOT??
From
A  B = C
both forms
B = C  A ((A subtracted on both sides))
and
B = A  C ((B added and C subtracted on both sides))
are equivalent, because you just need to multiply one of the equations by 1 to yield in the other equation.
But what do you personally used as a 'bridge' / reminder to approach it the right way at once?
(most of the item I end up trying B = A  C and get it wrong)
I don't understand. I make equivalence transformations until the unknown variable is isolated (or else I do not know how to continue). In the given example I'm interested in B, not in 1 times B.
#5227948 Get the distance of an intersection
Posted by haegarr on 08 May 2015  07:46 AM
So like this?
if(this.direction.dot(point.sub(this.origin)) > 0)
Yep, seems me principally okay.
#5227937 Get the distance of an intersection
Posted by haegarr on 08 May 2015  06:52 AM
Hi and thanks for your detailed answer:
If this is not wanted, then the dotproduct of the ray's direction vector with the difference vector from the ray's origin to the intersection point can be used to determine whether the intersection lies "before" or "behind" the origin.
Which value should the result be to be in front (so in the rays direction) of the origin?
The dotproduct yields in 0 if the both vectors are orthogonal (or the distance is zero, i.e. the intersection is exactly at the ray origin), a value greater than 0 if the both vectors point roughly in the same direction, and a negative value if the both vectors point roughly in reverse directions.
So, if you compute the difference vector v from the ray origin o to the intersection point p
v := p  o
then you can expect positive values of the dotproduct for intersections points in direction of the ray, and negative values for points in antidirection. (The sign will reverse if you use difference vectors from the intersection point to the ray origin, i.e. o  p.)
#5227922 Get the distance of an intersection
Posted by haegarr on 08 May 2015  05:00 AM
1.) This statement
I have this code which intersects a ray and line segment:
is wrong. The code snippet shows at most an intersection of a ray with a line, but not with a line segment. There is nothing that detects whether the ray passes past the endpoints of the segment.
2.) This line
var y3 = seg.direction.y;
should obviously be
var y3 = seg.origin.y;
_
3.) To come to the originally asked question:
a) Since all points are on the same ray, the distance of the ray's origin and the intersection point can be used
ai := sqrt( ( xi  x1 ) * ( xi  x1 ) + ( yi  y1 ) * ( yi  y1 ) )
from which the minimum is the valid point.
Notice that this kind of solution takes into account intersections both in direction of as well as in antidirection of the ray. If this is not wanted, then the dotproduct of the ray's direction vector with the difference vector from the ray's origin to the intersection point can be used to determine whether the intersection lies "before" or "behind" the origin.
Optimization: Since you just need the relative ordering of intersections, you can use any transformation that does not change that order. It allows for dropping the (costly) squareroot:
ai := ( xi  x1 ) * ( xi  x1 ) + ( yi  y1 ) * ( yi  y1 )
#5227910 arrays
Posted by haegarr on 08 May 2015  12:57 AM
I'm not familiar with that SDK, but the following issues seem me exist:
1.) Reading 16 floats if just 1 is needed is wasteful.
2.) Allocating another 16 floats if 1 is used is wasteful.
3.) Within XPLMSetDatav you take the address of the 10th element and apply the unary negation!?
IMHO the needed code snippet looks like so (but is untested):
float value; XPLMGetDatavf(pnlBri, &value, 10, 1); value = 100value; XPLMSetDatavf(pnlBri, &value, 10, 1);