A nice change of pace for me, I did a little script that will parse PTH files. It is licensed out as MIT as with all of my work on LFS, so feel free to use it for anything.
struct NodeLap // Car info in 6 bytes - there is an array of these in the NLP (below)
{
[B]word Node; // current path node[/B]
word Lap; // current lap
byte PLID; // player's unique id
byte Position; // current race position : 0 = unknown, 1 = leader, etc...
};
<?php
public function onTrackChange(IS_STA $STA)
{
$this->PTH = new PTH(ROOTDIR . '/data/pth/' . $STA->Track . '.pth');
}
?>
<?php
public function onMultiCarInfo(IS_MCI $MCI)
{
foreach ($MCI->Info as $Info)
{
if ($this->isInPoly($Info->X, $Info->Y, $this->PTH->Nodes[$Info->Node]->toPolyRoad())
continue; # They are within the node.
# If we get here, then they are NOT on the track.
}
}
?>
<?php
public function toPolyLimit()
{
return array
(
array
(
'x' => $this->Center->X + $this->Limit->Left,
'y' => $this->Center->Y + $this->Limit->Left
), array
(
'x' => $this->Cetner->X + $this->Limit->Right,
'y' => $this->Cetner->Y + $this->Limit->Right
)
);
}
public function toPolyRoad()
{
return array
(
array
(
'x' => $this->Center->X + $this->Road->Left,
'y' => $this->Center->Y + $this->Road->Left
), array
(
'x' => $this->Cetner->X + $this->Road->Right,
'y' => $this->Cetner->Y + $this->Road->Right
)
);
}
?>
<?php
public function toPolyLimit()
{
return array
(
array
(
'x' => $this->Center->X + $this->Limit->Left * cos(atan2($this->Direction->X, $this->Direction->Y)),
'y' => $this->Center->Y + $this->Limit->Left * sin(atan2($this->Direction->X, $this->Direction->Y))
), array
(
'x' => $this->Center->X + $this->Limit->Right * cos(atan2($this->Direction->X, $this->Direction->Y)),
'y' => $this->Center->Y + $this->Limit->Right * sin(atan2($this->Direction->X, $this->Direction->Y))
)
);
}
public function toPolyRoad()
{
return array
(
array
(
'x' => $this->Center->X + $this->Road->Left * cos(atan2($this->Direction->X, $this->Direction->Y)),
'y' => $this->Center->Y + $this->Road->Left * sin(atan2($this->Direction->X, $this->Direction->Y))
), array
(
'x' => $this->Center->X + $this->Road->Right * cos(atan2($this->Direction->X, $this->Direction->Y)),
'y' => $this->Center->Y + $this->Road->Right * sin(atan2($this->Direction->X, $this->Direction->Y))
)
);
}
?>
<?php
function getOuterX($x, $deltaX, $dirX, dirY) {
return 1280 + $x/65536 + $deltaX*cos(atan2($dirX, $dirY));
}
function getOuterY($y, $deltaY, $dirX, dirY) {
return 1280 - $y/65536 + $deltaY*sin(atan2($dirX, $dirY));
}
?>
<?php
function getOuterX($x, $deltaX, $dirX, dirY) {
return 1280 + $x/65536 + $deltaX*cos(atan2($dirX, $dirY));
}
function getOuterY($y, $deltaY, $dirX, dirY) {
return 1280 + $y/65536 - $deltaY*sin(atan2($dirX, $dirY));
}
?>
<?php
public function toPolyLimit()
{
return array
(
array
(
'x' => $this->Center->X + $this->Limit->Left * cos(atan2($this->Direction->X, $this->Direction->Y)) * 65536,
'y' => $this->Center->Y - $this->Limit->Left * sin(atan2($this->Direction->X, $this->Direction->Y)) * 65536
), array
(
'x' => $this->Center->X + $this->Limit->Right * cos(atan2($this->Direction->X, $this->Direction->Y)) * 65536,
'y' => $this->Center->Y - $this->Limit->Right * sin(atan2($this->Direction->X, $this->Direction->Y)) * 65536
)
);
}
public function toPolyRoad()
{
return array
(
array
(
'x' => $this->Center->X + $this->Road->Left * cos(atan2($this->Direction->X, $this->Direction->Y)) * 65536,
'y' => $this->Center->Y - $this->Road->Left * sin(atan2($this->Direction->X, $this->Direction->Y)) * 65536
), array
(
'x' => $this->Center->X + $this->Road->Right * cos(atan2($this->Direction->X, $this->Direction->Y)) * 65536,
'y' => $this->Center->Y - $this->Road->Right * sin(atan2($this->Direction->X, $this->Direction->Y)) * 65536
)
);
}
?>
<?php
public function isInPoly($x, $y, array $poly1, , array $poly2)
{
$x12 = $poly1[1]['x'] - $poly1[0]['x'];
$x21 = $poly1[0]['x'] - $poly1[1]['x'];
$x13 = $poly2[1]['x'] - $poly1[0]['x'];
$x31 = $poly1[0]['x'] - $poly2[1]['x'];
$x23 = $poly2[1]['x'] - $poly1[1]['x'];
$x41 = $poly1[0]['x'] - $poly2[0]['x'];
$x34 = $poly2[0]['x'] - $poly2[1]['x'];
$x43 = $poly2[1]['x'] - $poly2[0]['x'];
$x1p = $x - $poly1[0]['x'];
$x2p = $x - $poly1[1]['x'];
$x3p = $x - $poly2[1]['x'];
$x4p = $x - $poly2[0]['x'];
$y12 = $poly1[1]['y'] - $poly1[0]['y'];
$y21 = $poly1[0]['y'] - $poly1[1]['y'];
$y13 = $poly2[1]['y'] - $poly1[0]['y'];
$y31 = $poly1[0]['y'] - $poly2[1]['y'];
$y23 = $poly2[1]['y'] - $poly1[1]['y'];
$y41 = $poly1[0]['y'] - $poly2[0]['y'];
$y34 = $poly2[0]['y'] - $poly2[1]['y'];
$y43 = $poly2[1]['y'] - $poly2[0]['y'];
$y1p = $y - $poly1[0]['y'];
$y2p = $y - $poly1[1]['y'];
$y3p = $y - $poly2[1]['y'];
$y4p = $y - $poly2[0]['y'];
return (( ($x12*$y13 - $y12*$x13)*($x12*$y1p - $y12*$x1p) >= 0 ) && ( ($x23*$y21 - $y23*$x21)*($x23*$y2p - $y23*$x2p) >= 0 ) && ( ($x34*$y31 - $y34*$x31)*($x34*$y3p - $y34*$x3p) >= 0 ) && ( ($x41*$y43 - $y41*$x43)*($x41*$y4p - $y41*$x4p) >= 0 )) ? TRUE : FALSE;
}
?>
<?php
php
/*# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # *
# #
# This file contains a PHP adaptation of code (imagemap.c) originally #
# written by Brian J. Fox ([email protected]) for MetaHTML 5.01 #
# #
# http://directory.fsf.org/GNU/metahtml.html #
# #
# Draw a horizontal line from $X, $Y extending inf in the positive #
# X-axis. Count the number of times that line crosses the lines created #
# by connecting adjacent vertices of the polygon. If that number is #
# even, then $X, $Y is "outside" of the polygon, if odd, then "inside". #
* # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #*/
class Point
{
public $x;
public $y;
};
function inPoly ($X, $Y, array $points)
{
$min_x = $max_x = $min_y = $max_y = NULL;
# Count vertices
$vertices = count($points);
# Close the polygon if it isn't already closed.
$i = $vertices - 1;
if (($points[$i]->x != $points[0]->x) OR ($points[$i]->y != $points[0]->y))
{
++$i;
++$vertices;
$points[$i] = new Point;
$points[$i]->x = $points[0]->x;
$points[$i]->y = $points[0]->y;
$points[$i + 1] = NULL;
}
# Now check to see if the point falls within the rectangle which encloses the entire polygon.
# If not, it certainly isn't inside.
for ($i = 0; $points[$i] != NULL; ++$i)
{
$min_x = (($min_x === NULL) OR ($points[$i]->x < $min_x)) ? $points[$i]->x : $min_x;
$min_y = (($min_y === NULL) OR ($points[$i]->y < $min_y)) ? $points[$i]->y : $min_y;
$max_x = (($max_x === NULL) OR ($points[$i]->x > $max_x)) ? $points[$i]->x : $max_x;
$max_y = (($max_y === NULL) OR ($points[$i]->y > $max_y)) ? $points[$i]->y : $max_y;
}
# Is $X, $Y within the rectangle defined by $min_x, $max_y, $max_x, $min_y?
if (($X < $min_x) OR ($X > $max_x) OR ($Y < $min_y) OR ($Y > $max_y))
return FALSE;
# The point falls within the polygon. Check adjacent vertices.
$lines_crossed = 0;
for ($i = 1; $points[$i] != NULL; ++$i)
{
$p1 =& $points[$i - 1];
$p2 =& $points[$i];
$min_x = min ($p1->x, $p2->x);
$max_x = max ($p1->x, $p2->x);
$min_y = min ($p1->y, $p2->y);
$max_y = max ($p1->y, $p2->y);
# We need to know if the point falls within the rectangle defined by the maximum vertices of the vector.
if (($X < $min_x) OR ($X > $max_x) OR ($Y < $min_y) OR ($Y > $max_y))
{
# Not within the rectangle. Great!
# If it is to the left of the rectangle and in between the $Y then it crosses the line.
if (($X < $min_x) AND ($Y > $min_y) AND ($Y < $max_y))
++$lines_crossed;
continue;
}
# Find the intersection of the line -inf $Y, +inf, $Y] and $p1-x, $p1-y, $p2-x, $p2-y].
# If the location of the intercept is to the right of $X, then the line will be crossed.
$slope = ($p1->y - $p2->y) / ($p1->x - $p2->x);
if ((($Y - ($p1->y - ($slope * $p1->x))) / $slope) >= $X)
++$lines_crossed;
}
return ($lines_crossed & 1) ? TRUE : FALSE;
}
?>