PHP interpolate points on cardinal curve
I have a set of x,y points and wish to interpolate a set of higher detai开发者_StackOverflow社区led points in-between on a cardinal curve in php
I can't get my head around how to turn the mathematical formula on the web to a php function or class
can any one help?
Here's the solution that I've come up with in case any one else is facing the same problem
function caculate_cardinal_points($points,$tension=0.5,$steps=20) {
$return_points = array();
$tangents = array();
// calculate tangents
$previous_point = false;
for($i=0;$i<count($points);$i++) {
$px = $points[$i][0];
$py = $points[$i][1];
if (isset($points[$i+1]) && isset($points[$i-1])) {
$tx = ($tension * (($points[$i+1][0]-$px) - ($points[$i-1][0]-$px)));
$ty = ($tension * (($points[$i+1][1]-$py) - ($points[$i-1][1]-$py)));
} elseif (isset($points[$i+1])) {
$tx = ($tension * (($points[$i+1][0]-$px) - ($points[$i][0]-$px)));
$ty = ($tension * (($points[$i+1][1]-$py) - ($points[$i][1]-$py)));
} elseif (isset($points[$i-1])) {
$tx = ($tension * (($points[$i][0]-$px) - ($points[$i-1][0]-$px)));
$ty = ($tension * (($points[$i][1]-$py) - ($points[$i-1][1]-$py)));
}
$tangents[] = array($tx,$ty);
$previous_x = $px;
$previous_y = $py;
}
// interpolate
for($i=0;$i<count($tangents)-1;$i++) {
$p0x = $points[$i][0];
$p0y = $points[$i][1];
$p1x = $points[$i+1][0];
$p1y = $points[$i+1][1];
$t0x = $tangents[$i][0];
$t0y = $tangents[$i][1];
$t1x = $tangents[$i+1][0];
$t1y = $tangents[$i+1][1];
$previous_x = $p0x;
$previous_y = $p0y;
$return_points[] = array($p0x,$p0y);
for ($t=0; $t < $steps; $t++) {
$s = $t / $steps; // scale s to go from 0 to 1
$h1 = 2*pow($s,3) - 3*pow($s,2) + 1;
$h2 = pow($s,3) - 2*pow($s,2) + $s;
$h3 = -2*pow($s,3) + 3*pow($s,2);
$h4 = pow($s,3) - pow($s,2);
$x = $h1*$p0x+$h2*$t0x+$h3*$p1x+$h4*$t1x;
$y = $h1*$p0y+$h2*$t0y+$h3*$p1y+$h4*$t1y;
$return_points[] = array($x,$y);
$previous_x = $x;
$previous_y = $y;
}
$return_points[] = array($p1x,$p1y);
}
return $return_points;
}
Here an example of it in use:
<?php
$width = 600;
$height = 600;
$factor = 1;
$steps = 20;
$tension = .25;
$blue = 0x00257ac7;
$green = 0x0096be44;
$black = 0x009999999;
$purple = 0x00b5499a;
$red = 0x00ff5555;
$bgreen = 0x0000ff00;
$img = imagecreatetruecolor( $width*$factor, $height*$factor );
// background fill
imagefill($img, 0, 0, 0x00dddddd);
// some control points
$points = array(
array(120 *$factor,140 *$factor),
array(140 *$factor,350*$factor),
array(180 *$factor,500*$factor),
array(430*$factor,350*$factor),
array(390*$factor,210*$factor),
array(540*$factor,120 *$factor)
);
$last_point = false;
foreach($points as $point) {
imagefilledellipse($img,$point[0],$point[1],8*$factor,8*$factor,$blue);
if ($last_point) {
imageline($img,$point[0],$point[1],$last_point[0],$last_point[1],$purple);
}
$last_point = $point;
}
$tangets = array();
// calculate tangents
$previous_point = false;
for($i=0;$i<count($points);$i++) {
$px = $points[$i][0];
$py = $points[$i][1];
if (isset($points[$i+1]) && isset($points[$i-1])) {
$tx = ($tension * (($points[$i+1][0]-$px) - ($points[$i-1][0]-$px)));
$ty = ($tension * (($points[$i+1][1]-$py) - ($points[$i-1][1]-$py)));
} elseif (isset($points[$i+1])) {
$tx = ($tension * (($points[$i+1][0]-$px) - ($points[$i][0]-$px)));
$ty = ($tension * (($points[$i+1][1]-$py) - ($points[$i][1]-$py)));
} elseif (isset($points[$i-1])) {
$tx = ($tension * (($points[$i][0]-$px) - ($points[$i-1][0]-$px)));
$ty = ($tension * (($points[$i][1]-$py) - ($points[$i-1][1]-$py)));
}
$tangets[] = array($tx,$ty);
imageline($img,$px+$tx,$py+$ty,$points[$i][0],$points[$i][1],$black);
imagefilledellipse($img,$px+$tx,$py+$ty,4*$factor,4*$factor,$green);
imageline($img,$px-$tx,$py-$ty,$points[$i][0],$points[$i][1],$black);
imagefilledellipse($img,$px-$tx,$py-$ty,4*$factor,4*$factor,$green);
$previous_x = $px;
$previous_y = $py;
}
for($i=0;$i<count($tangets)-1;$i++) {
$p0x = $points[$i][0];
$p0y = $points[$i][1];
$p1x = $points[$i+1][0];
$p1y = $points[$i+1][1];
$t0x = $tangets[$i][0];
$t0y = $tangets[$i][1];
$t1x = $tangets[$i+1][0];
$t1y = $tangets[$i+1][1];
$previous_x = $p0x;
$previous_y = $p0y;
for ($t=0; $t < $steps; $t++) {
$s = $t / $steps; // scale s to go from 0 to 1
$h1 = 2*pow($s,3) - 3*pow($s,2) + 1;
$h2 = pow($s,3) - 2*pow($s,2) + $s;
$h3 = -2*pow($s,3) + 3*pow($s,2);
$h4 = pow($s,3) - pow($s,2);
$x = $h1*$p0x+$h2*$t0x+$h3*$p1x+$h4*$t1x;
$y = $h1*$p0y+$h2*$t0y+$h3*$p1y+$h4*$t1y;
//imageline($img,$previous_x,$previous_y,$x,$y,$red);
$previous_x = $x;
$previous_y = $y;
}
//imageline($img,$previous_x,$previous_y,$p1x,$p1y,$red);
}
$line_points = caculate_cardinal_points($points);
$previous_point = false;
foreach($line_points as $point) {
if ($previous_point) {
imageline($img,$previous_point[0],$previous_point[1],$point[0],$point[1],$red);
}
$previous_point = $point;
}
$resampled = imagecreatetruecolor( $width, $height);
imagecopyresampled($resampled,$img,0,0,0,0,$width,$height,$width*$factor,$height*$factor);
header( "Content-Type: image/png" );
imagepng($resampled);
imagedestroy($img);
imagedestroy($resampled);
精彩评论