Issues (459)

src/graph/RectPattern3DPlane.php (1 issue)

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Graph;
8
9
/**
10
 * @class RectPattern3DPlane
11
 * // Implements "3D" plane pattern
12
 */
13
class RectPattern3DPlane extends RectPattern
14
{
15
    private $alpha = 50; // Parameter that specifies the distance
16
    // to "simulated" horizon in pixel from the
17
    // top of the band. Specifies how fast the lines
18
    // converge.
19
20
    public function __construct($aColor = 'black', $aWeight = 1)
21
    {
22
        parent::__construct($aColor, $aWeight);
23
        $this->SetDensity(10); // Slightly larger default
24
    }
25
26
    public function SetHorizon($aHorizon)
27
    {
28
        $this->alpha = $aHorizon;
29
    }
30
31
    public function DoPattern($aImg)
32
    {
33
        // "Fake" a nice 3D grid-effect.
34
        $x0       = $this->rect->x + $this->rect->w / 2;
35
        $y0       = $this->rect->y;
36
        $x1       = $x0;
37
        $y1       = $this->rect->ye;
38
        $x0_right = $x0;
39
        $x1_right = $x1;
40
41
        // BTW "apa" means monkey in Swedish but is really a shortform for
42
        // "alpha+a" which was the labels I used on paper when I derived the
43
        // geometric to get the 3D perspective right.
44
        // $apa is the height of the bounding rectangle plus the distance to the
45
        // artifical horizon (alpha)
46
        $apa = $this->rect->h + $this->alpha;
47
48
        // Three cases and three loops
49
        // 1) The endpoint of the line ends on the bottom line
50
        // 2) The endpoint ends on the side
51
        // 3) Horizontal lines
52
53
        // Endpoint falls on bottom line
54
        $middle = $this->rect->x + $this->rect->w / 2;
55
        $dist   = $this->linespacing;
56
        $factor = $this->alpha / ($apa);
57
        while ($x1 > $this->rect->x) {
58
            $aImg->Line($x0, $y0, $x1, $y1);
59
            $aImg->Line($x0_right, $y0, $x1_right, $y1);
60
            $x1       = $middle - $dist;
61
            $x0       = $middle - $dist * $factor;
62
            $x1_right = $middle + $dist;
63
            $x0_right = $middle + $dist * $factor;
64
            $dist += $this->linespacing;
65
        }
66
67
        // Endpoint falls on sides
68
        $dist -= $this->linespacing;
69
        $d = $this->rect->w / 2;
70
        $c = $apa - $d * $apa / $dist;
71
        while ($x0 > $this->rect->x) {
72
            $aImg->Line($x0, $y0, $this->rect->x, $this->rect->ye - $c);
73
            $aImg->Line($x0_right, $y0, $this->rect->xe, $this->rect->ye - $c);
74
            $dist += $this->linespacing;
75
            $x0       = $middle - $dist * $factor;
76
            $x1       = $middle - $dist;
0 ignored issues
show
The assignment to $x1 is dead and can be removed.
Loading history...
77
            $x0_right = $middle + $dist * $factor;
78
            $c        = $apa - $d * $apa / $dist;
79
        }
80
81
        // Horizontal lines
82
        // They need some serious consideration since they are a function
83
        // of perspective depth (alpha) and density (linespacing)
84
        $x0 = $this->rect->x;
85
        $x1 = $this->rect->xe;
86
        $y  = $this->rect->ye;
87
88
        // The first line is drawn directly. Makes the loop below slightly
89
        // more readable.
90
        $aImg->Line($x0, $y, $x1, $y);
91
        $hls = $this->linespacing;
92
93
        // A correction factor for vertical "brick" line spacing to account for
94
        // a) the difference in number of pixels hor vs vert
95
        // b) visual apperance to make the first layer of "bricks" look more
96
        // square.
97
        $vls = $this->linespacing * 0.6;
98
99
        $ds = $hls * ($apa - $vls) / $apa;
100
        // Get the slope for the "perspective line" going from bottom right
101
        // corner to top left corner of the "first" brick.
102
103
        // Uncomment the following lines if you want to get a visual understanding
104
        // of what this helpline does. BTW this mimics the way you would get the
105
        // perspective right when drawing on paper.
106
        /*
107
        $x0 = $middle;
108
        $y0 = $this->rect->ye;
109
        $len=floor(($this->rect->ye-$this->rect->y)/$vls);
110
        $x1 = $middle+round($len*$ds);
111
        $y1 = $this->rect->ye-$len*$vls;
112
        $aImg->PushColor("red");
113
        $aImg->Line($x0,$y0,$x1,$y1);
114
        $aImg->PopColor();
115
         */
116
117
        $y -= $vls;
118
        $k    = ($this->rect->ye - ($this->rect->ye - $vls)) / ($middle - ($middle - $ds));
119
        $dist = $hls;
120
        while ($y > $this->rect->y) {
121
            $aImg->Line($this->rect->x, $y, $this->rect->xe, $y);
122
            $adj = $k * $dist / (1 + $dist * $k / $apa);
123
            if ($adj < 2) {
124
                $adj = 1;
125
            }
126
127
            $y = $this->rect->ye - round($adj);
128
            $dist += $hls;
129
        }
130
    }
131
}
132