使用PHP和GD创建平滑曲线图

使用PHP和GD创建平滑曲线图_第1张图片
使用PHP和GD创建平滑曲线图_第2张图片

Smooth Curve Graphs with PHP and GD. Today I have new article for PHP. I will tell you about drawing graphs with GD. Plus – we will smooth our graph with curve lines using cubic splines interpolation method. You can read more about method at Wiki.

使用PHP和GD平滑曲线图。 今天,我有关于PHP的新文章。 我将告诉您有关使用GD绘制图形的信息。 另外–我们将使用三次样条插值方法使用曲线平滑图形。 您可以在Wiki上了解有关方法的更多信息 。

现场演示

[sociallocker]

[社交储物柜]

打包下载

[/sociallocker]

[/ sociallocker]

Now – download the source files and lets start coding !

现在–下载源文件并开始编码!

步骤1. HTML (Step 1. HTML)

Here are HTML layout for our example page:

这是示例页面HTML布局:

index.html (index.html)



    
        
        Smooth Curve Graphs with PHP and GD | Script Tutorials
        
    
    
        



    
        
        Smooth Curve Graphs with PHP and GD | Script Tutorials
        
    
    
        

步骤2. CSS (Step 2. CSS)

Now, lets define all used styles:

现在,让我们定义所有使用的样式:

css / main.css (css/main.css)

*{
    margin:0;
    padding:0;
}
body {
    background-repeat:no-repeat;
    background-color:#bababa;
    background-image: -webkit-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -moz-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -o-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
    min-height:600px;
}
footer {
    background-color:#212121;
    bottom:0;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    left:0;
    position:fixed;
    width:100%;
    z-index:100;
}
footer h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
footer a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
footer .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
.container {
    border:3px #111 solid;
    margin:20px auto;
    padding:20px;
    position:relative;
    width:550px;
    height:430px;
    border-radius:15px;
    -moz-border-radius:15px;
    -webkit-border-radius:15px;
}

*{
    margin:0;
    padding:0;
}
body {
    background-repeat:no-repeat;
    background-color:#bababa;
    background-image: -webkit-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -moz-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -o-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
    min-height:600px;
}
footer {
    background-color:#212121;
    bottom:0;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    left:0;
    position:fixed;
    width:100%;
    z-index:100;
}
footer h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
footer a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
footer .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
.container {
    border:3px #111 solid;
    margin:20px auto;
    padding:20px;
    position:relative;
    width:550px;
    height:430px;
    border-radius:15px;
    -moz-border-radius:15px;
    -webkit-border-radius:15px;
}

And first step and second – not very important of course, most important will now:

第一步和第二步-当然不是很重要,现在最重要的是:

步骤3. PHP (Step 3. PHP)

This is our image generator (of graph):

这是我们的图像生成器(图):

smooth_graph.php (smooth_graph.php)

drawDots($vImage, $vDotColor, 10, GRAPH_HEIGHT, 8);
$oCurve = new CubicSplines();
$vColor = imagecolorallocate($vImage, 225, 64, 64);
$iStart = microtime(1);
if ($oCurve) {
    $oCurve->setInitCoords($aCoords, 1);
    $r = $oCurve->processCoords();
    if ($r)
        $curveGraph = new Plot($r);
    else
        continue;
} else {
    $curveGraph = $oPlot;
}
$curveGraph->drawLine($vImage, $vColor, 10, GRAPH_HEIGHT);
// unset($oCurve);
$sTime = sprintf("%1.4f", microtime(1) - $iStart);
imagefilledrectangle($vImage, 0, GRAPH_HEIGHT, GRAPH_WIDTH + 50, $vImagegHeight, $vBgColor);
$oPlot->drawAxis($vImage, $vAxisColor, 10, GRAPH_HEIGHT);
$iPanelY = GRAPH_HEIGHT;
imagefilledrectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vColor);
imagerectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vAxisColor);
imagettftext($vImage, 10, 0, 30, $iPanelY + 20, $vTextColor, 'Ds-digib.ttf', 'Cubic splines in PHP for graphs:         ' . $sTime . ' sec');
header("Content-type: image/png");
imagepng($vImage);
imagedestroy($vImage);
?>

drawDots($vImage, $vDotColor, 10, GRAPH_HEIGHT, 8);
$oCurve = new CubicSplines();
$vColor = imagecolorallocate($vImage, 225, 64, 64);
$iStart = microtime(1);
if ($oCurve) {
    $oCurve->setInitCoords($aCoords, 1);
    $r = $oCurve->processCoords();
    if ($r)
        $curveGraph = new Plot($r);
    else
        continue;
} else {
    $curveGraph = $oPlot;
}
$curveGraph->drawLine($vImage, $vColor, 10, GRAPH_HEIGHT);
// unset($oCurve);
$sTime = sprintf("%1.4f", microtime(1) - $iStart);
imagefilledrectangle($vImage, 0, GRAPH_HEIGHT, GRAPH_WIDTH + 50, $vImagegHeight, $vBgColor);
$oPlot->drawAxis($vImage, $vAxisColor, 10, GRAPH_HEIGHT);
$iPanelY = GRAPH_HEIGHT;
imagefilledrectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vColor);
imagerectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vAxisColor);
imagettftext($vImage, 10, 0, 30, $iPanelY + 20, $vTextColor, 'Ds-digib.ttf', 'Cubic splines in PHP for graphs:         ' . $sTime . ' sec');
header("Content-type: image/png");
imagepng($vImage);
imagedestroy($vImage);
?>

In this file I using 2 another classes (as separated service classes):

在这个文件中,我使用了另外两个类(作为分离的服务类):

classes / Plot.php (classes/Plot.php)

aCoords = &$aCoords;
    }
    public function drawLine($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        reset($this->aCoords);
        list($iPrevX, $iPrevY) = each($this->aCoords);
        while (list ($x, $y) = each($this->aCoords)) {
            imageline($vImage, $iPosX + round($iPrevX), $iPosY - round($iPrevY), $iPosX + round($x), $iPosY - round($y), $vColor);
            $iPrevX = $x;
            $iPrevY = $y;
        }
    }
    public function drawDots($vImage, $vColor, $iPosX = 0, $iPosY = false, $iDotSize = 1) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        $vBorderColor = imagecolorallocate($vImage, 0, 0, 0);
        foreach ($this->aCoords as $x => $y) {
            imagefilledellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vColor);
            imageellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vBorderColor);
        }
    }
    public function drawAxis($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        $vImageWidth = imagesx($vImage);
        imageline($vImage, $iPosX, $iPosY, $iPosX, 0, $vColor);
        imageline($vImage, $iPosX, $iPosY, $vImageWidth, $iPosY, $vColor);
        imagefilledpolygon($vImage, array($iPosX, 0, $iPosX - 3, 5, $iPosX + 3, 5), 3, $vColor);
        imagefilledpolygon($vImage, array($vImageWidth, $iPosY, $vImageWidth - 5, $iPosY - 3, $vImageWidth - 5, $iPosY + 3), 3, $vColor);
    }
}
?>

aCoords = &$aCoords;
    }
    public function drawLine($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        reset($this->aCoords);
        list($iPrevX, $iPrevY) = each($this->aCoords);
        while (list ($x, $y) = each($this->aCoords)) {
            imageline($vImage, $iPosX + round($iPrevX), $iPosY - round($iPrevY), $iPosX + round($x), $iPosY - round($y), $vColor);
            $iPrevX = $x;
            $iPrevY = $y;
        }
    }
    public function drawDots($vImage, $vColor, $iPosX = 0, $iPosY = false, $iDotSize = 1) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        $vBorderColor = imagecolorallocate($vImage, 0, 0, 0);
        foreach ($this->aCoords as $x => $y) {
            imagefilledellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vColor);
            imageellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vBorderColor);
        }
    }
    public function drawAxis($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
        $vImageWidth = imagesx($vImage);
        imageline($vImage, $iPosX, $iPosY, $iPosX, 0, $vColor);
        imageline($vImage, $iPosX, $iPosY, $vImageWidth, $iPosY, $vColor);
        imagefilledpolygon($vImage, array($iPosX, 0, $iPosX - 3, 5, $iPosX + 3, 5), 3, $vColor);
        imagefilledpolygon($vImage, array($vImageWidth, $iPosY, $vImageWidth - 5, $iPosY - 3, $vImageWidth - 5, $iPosY + 3), 3, $vColor);
    }
}
?>

和类/CubicSplines.php (and classes/CubicSplines.php)

aCrdX = array();
        $this->aCrdY = array();
        $this->aCoords = array();
        ksort($aCoords);
        foreach ($aCoords as $x => $y) {
            $this->aCrdX[] = $x;
            $this->aCrdY[] = $y;
        }
        $this->iMinX = $iMinX;
        $this->iMaxX = $iMaxX;
        if ($this->iMinX == -1)
            $this->iMinX = min($this->aCrdX);
        if ($this->iMaxX == -1)
            $this->iMaxX = max($this->aCrdX);
        $this->iStep = $iStep;
    }
    public function setInitCoords(&$aCoords, $iStep = 1, $iMinX = -1, $iMaxX = -1) {
        $this->aSplines = array();
        if (count($aCoords) < 4) {
            return false;
        }
        $this->prepareCoords($aCoords, $iStep, $iMinX, $iMaxX);
        $this->buildSpline($this->aCrdX, $this->aCrdY, count($this->aCrdX));
    }
    public function processCoords() {
        for ($x = $this->iMinX; $x <= $this->iMaxX; $x += $this->iStep) {
            $this->aCoords[$x] = $this->funcInterp($x);
        }
        return $this->aCoords;
    }
    private function buildSpline($x, $y, $n) {
        for ($i = 0; $i < $n; ++$i) {
            $this->aSplines[$i]['x'] = $x[$i];
            $this->aSplines[$i]['a'] = $y[$i];
        }
        $this->aSplines[0]['c'] = $this->aSplines[$n - 1]['c'] = 0;
        $alpha[0] = $beta[0] = 0;
        for ($i = 1; $i < $n - 1; ++$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $h_i1 = $x[$i + 1] - $x[$i];
            $A = $h_i;
            $C = 2.0 * ($h_i + $h_i1);
            $B = $h_i1;
            $F = 6.0 * (($y[$i + 1] - $y[$i]) / $h_i1 - ($y[$i] - $y[$i - 1]) / $h_i);
            $z = ($A * $alpha[$i - 1] + $C);
            $alpha[$i] = - $B / $z;
            $beta[$i] = ($F - $A * $beta[$i - 1]) / $z;
        }
        for ($i = $n - 2; $i > 0; --$i) {
            $this->aSplines[$i]['c'] = $alpha[$i] * $this->aSplines[$i + 1]['c'] + $beta[$i];
        }
        for ($i = $n - 1; $i > 0; --$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $this->aSplines[$i]['d'] = ($this->aSplines[$i]['c'] - $this->aSplines[$i - 1]['c']) / $h_i;
            $this->aSplines[$i]['b'] = $h_i * (2.0 * $this->aSplines[$i]['c'] + $this->aSplines[$i - 1]['c']) / 6.0 + ($y[$i] - $y[$i - 1]) / $h_i;
        }
    }
    private function funcInterp($x) {
        $n = count($this->aSplines);
        if ($x <= $this->aSplines[0]['x'])  {
            $s = $this->aSplines[1];
        } else {
            if ($x >= $this->aSplines[$n - 1]['x']) {
                $s = $this->aSplines[$n - 1];
            } else {
                $i = 0;
                $j = $n - 1;
                while ($i + 1 < $j) {
                    $k = $i + ($j - $i) / 2;
                    if ($x <= $this->aSplines[$k]['x']) {
                        $j = $k;
                    } else {
                        $i = $k;
                    }
                }
                $s = $this->aSplines[$j];
            }
        }
        $dx = ($x - $s['x']);
        return $s['a'] + ($s['b'] + ($s['c'] / 2.0 + $s['d'] * $dx / 6.0) * $dx) * $dx;
    }
}
?>

aCrdX = array();
        $this->aCrdY = array();
        $this->aCoords = array();
        ksort($aCoords);
        foreach ($aCoords as $x => $y) {
            $this->aCrdX[] = $x;
            $this->aCrdY[] = $y;
        }
        $this->iMinX = $iMinX;
        $this->iMaxX = $iMaxX;
        if ($this->iMinX == -1)
            $this->iMinX = min($this->aCrdX);
        if ($this->iMaxX == -1)
            $this->iMaxX = max($this->aCrdX);
        $this->iStep = $iStep;
    }
    public function setInitCoords(&$aCoords, $iStep = 1, $iMinX = -1, $iMaxX = -1) {
        $this->aSplines = array();
        if (count($aCoords) < 4) {
            return false;
        }
        $this->prepareCoords($aCoords, $iStep, $iMinX, $iMaxX);
        $this->buildSpline($this->aCrdX, $this->aCrdY, count($this->aCrdX));
    }
    public function processCoords() {
        for ($x = $this->iMinX; $x <= $this->iMaxX; $x += $this->iStep) {
            $this->aCoords[$x] = $this->funcInterp($x);
        }
        return $this->aCoords;
    }
    private function buildSpline($x, $y, $n) {
        for ($i = 0; $i < $n; ++$i) {
            $this->aSplines[$i]['x'] = $x[$i];
            $this->aSplines[$i]['a'] = $y[$i];
        }
        $this->aSplines[0]['c'] = $this->aSplines[$n - 1]['c'] = 0;
        $alpha[0] = $beta[0] = 0;
        for ($i = 1; $i < $n - 1; ++$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $h_i1 = $x[$i + 1] - $x[$i];
            $A = $h_i;
            $C = 2.0 * ($h_i + $h_i1);
            $B = $h_i1;
            $F = 6.0 * (($y[$i + 1] - $y[$i]) / $h_i1 - ($y[$i] - $y[$i - 1]) / $h_i);
            $z = ($A * $alpha[$i - 1] + $C);
            $alpha[$i] = - $B / $z;
            $beta[$i] = ($F - $A * $beta[$i - 1]) / $z;
        }
        for ($i = $n - 2; $i > 0; --$i) {
            $this->aSplines[$i]['c'] = $alpha[$i] * $this->aSplines[$i + 1]['c'] + $beta[$i];
        }
        for ($i = $n - 1; $i > 0; --$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $this->aSplines[$i]['d'] = ($this->aSplines[$i]['c'] - $this->aSplines[$i - 1]['c']) / $h_i;
            $this->aSplines[$i]['b'] = $h_i * (2.0 * $this->aSplines[$i]['c'] + $this->aSplines[$i - 1]['c']) / 6.0 + ($y[$i] - $y[$i - 1]) / $h_i;
        }
    }
    private function funcInterp($x) {
        $n = count($this->aSplines);
        if ($x <= $this->aSplines[0]['x'])  {
            $s = $this->aSplines[1];
        } else {
            if ($x >= $this->aSplines[$n - 1]['x']) {
                $s = $this->aSplines[$n - 1];
            } else {
                $i = 0;
                $j = $n - 1;
                while ($i + 1 < $j) {
                    $k = $i + ($j - $i) / 2;
                    if ($x <= $this->aSplines[$k]['x']) {
                        $j = $k;
                    } else {
                        $i = $k;
                    }
                }
                $s = $this->aSplines[$j];
            }
        }
        $dx = ($x - $s['x']);
        return $s['a'] + ($s['b'] + ($s['c'] / 2.0 + $s['d'] * $dx / 6.0) * $dx) * $dx;
    }
}
?>

现场演示

结论 (Conclusion)

I hope that you got interesting lesson for today. Good luck in your work!

希望您今天能从中学到有趣的一课。 祝您工作顺利!

翻译自: https://www.script-tutorials.com/smooth-curve-graphs-with-php-and-gd/

你可能感兴趣的:(html,python,css,less,php)