1<?php 2/** 3 * 3d Library 4 * 5 * PHP versions 5 6 * 7 * LICENSE: 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23/** 24 * Creates a HTML document, with embedded javascript code to draw, move, rotate 25 * and export the 3D-object at runtime 26 * 27 * @category Image 28 * @package Image_3D 29 * @author Jakob Westhoff <jakob@westhoffswelt.de> 30 */ 31class Image_3D_Driver_DynamicCanvas extends Image_3D_Driver 32{ 33 34 /** 35 * Width of the image 36 * 37 * @var integer 38 */ 39 protected $_x; 40 /** 41 * Height of the image 42 * 43 * @var integer 44 */ 45 protected $_y; 46 47 /** 48 * Polygones created during the rendering process 49 * 50 * @var array 51 */ 52 protected $_polygones; 53 54 /** 55 * Background Color of the rendered image 56 * 57 * @var string 58 */ 59 protected $_background; 60 61 62 /** 63 * Name of the Render created from the filename 64 * Needed for the correct creation of the Image3D java class 65 * 66 * @var mixed 67 */ 68 protected $_name; 69 70 /** 71 * Class constructor 72 */ 73 public function __construct() 74 { 75 $this->_image = ''; 76 77 $this->_polygones = array(); 78 $this->_background = array(); 79 } 80 81 /** 82 * Create the inital image 83 * 84 * @param float $x Width of the image 85 * @param float $y Height of the image 86 * 87 * @return void 88 */ 89 public function createImage($x, $y) 90 { 91 $this->_x = (int) $x; 92 $this->_y = (int) $y; 93 } 94 95 /** 96 * Set the background color of the image 97 * 98 * @param Image_3D_Color $color Desired background color of the image 99 * 100 * @return void 101 */ 102 public function setBackground(Image_3D_Color $color) 103 { 104 $colorarray = $this->_getRgba($color); 105 106 $this->_background = sprintf("{ r: %d, g: %d, b: %d, a:%.2f }", 107 $colorarray['r'], $colorarray['g'], 108 $colorarray['b'], $colorarray['a']); 109 } 110 111 /** 112 * Create an appropriate array representation from a Image_3D_Color object 113 * 114 * @param Image_3D_Color $color Color to transform to rgba syntax 115 * @param float $alpha optional Override the alpha value set in the Image_3D_Color object 116 * 117 * @return array Array of color values reflecting the different color 118 * components of the input object 119 */ 120 protected function _getRgba(Image_3D_Color $color, $alpha = null) 121 { 122 $values = $color->getValues(); 123 124 $values[0] = (int) round($values[0] * 255); 125 $values[1] = (int) round($values[1] * 255); 126 $values[2] = (int) round($values[2] * 255); 127 128 if ($alpha !== null) { 129 $values[3] = 1.0 - $alpha; 130 } else { 131 $values[3] = 1.0 - $values[3]; 132 } 133 134 return array('r' => $values[0], 'g' => $values[1], 'b' => $values[2], 'a' => $values[3]); 135 } 136 137 /** 138 * Add a polygon to the polygones array 139 * 140 * @param array $points Array of points which represent the polygon to add 141 * @param array $colors Array of maximal three colors. The second and the 142 * third color are allowed to be null 143 * 144 * @return void 145 */ 146 protected function _addPolygon(array $points, array $colors) 147 { 148 $this->_polygones[] = array("points" => $points, "colors" => $colors); 149 } 150 151 /** 152 * Draw a specified polygon 153 * 154 * @param Image_3D_Polygon $polygon Polygon to draw 155 * 156 * @return void 157 */ 158 public function drawPolygon(Image_3D_Polygon $polygon) 159 { 160 $pointarray = array(); 161 162 $points = $polygon->getPoints(); 163 foreach ($points as $key => $point) { 164 $pointarray[$key] = array('x' => $point->getX(), 'y' => $point->getY(), 'z' => $point->getZ()); 165 } 166 167 $this->_addPolygon($pointarray, 168 array($this->_getRgba($polygon->getColor()), 169 null, 170 null)); 171 } 172 173 /** 174 * Draw a specified polygon utilizing gradients between his points for 175 * color representation (Gauroud-Shading) 176 * 177 * @param Image_3D_Polygon $polygon Polygon to draw 178 * 179 * @return void 180 */ 181 public function drawGradientPolygon(Image_3D_Polygon $polygon) 182 { 183 $pointarray = array(); 184 $colorarray = array(); 185 186 $points = $polygon->getPoints(); 187 foreach ($points as $key => $point) { 188 $pointarray[$key] = array('x' => $point->getX(), 'y' => $point->getY(), 'z' => $point->getZ()); 189 $colorarray[$key] = $this->_getRgba($point->getColor()); 190 } 191 192 $this->_addPolygon($pointarray, $colorarray); 193 } 194 195 /** 196 * Convert php array to a javascript parsable data structure 197 * 198 * @param array $data Array to convert 199 * 200 * @return string Javascript readable representation of the given php array 201 */ 202 private function _arrayToJs(array $data) 203 { 204 $output = array(); 205 206 $assoiative = false; 207 // Is our array associative? 208 // Does anyone know a better/faster way to check this? 209 foreach (array_keys($data) as $key) { 210 if (is_int($key) === false) { 211 $assoiative = true; 212 break; 213 } 214 } 215 $output[] = $assoiative === true ? "{" : "["; 216 foreach ($data as $key => $value) { 217 $line = ''; 218 219 if ($assoiative === true) { 220 $line .= "\"$key\": "; 221 } 222 223 switch (gettype($value)) { 224 case "array": 225 $line .= $this->_arrayToJs($value); 226 break; 227 case "integer": 228 case "boolean": 229 $line .= $value; 230 break; 231 case "double": 232 $line .= sprintf("%.2f", $value); 233 break; 234 case "string": 235 $line .= "\"$value\""; 236 break; 237 case "NULL": 238 case "resource": 239 case "object": 240 $line .= "undefined"; 241 break; 242 } 243 244 if ($key !== end(array_keys($data))) { 245 $line .= ","; 246 } 247 $output[] = $line; 248 } 249 250 $output[] = $assoiative === true ? "}" : "]"; 251 252 // If the output array has more than 5 entries seperate them by a new line. 253 return implode(count($data) > 5 ? "\n" : " ", $output); 254 } 255 256 /** 257 * Get the Javascript needed for dynamic rendering, moving, rotating 258 * and exporting of the 3D Object 259 * 260 * @return string needed javascript code (with <script> tags) 261 */ 262 private function _getJs() 263 { 264 $identifiers = array( 265 "%polygones%", 266 "%background%", 267 "%width%", 268 "%height%", 269 "%uid%"); 270 271 $replacements = array( 272 $this->_arrayToJs($this->_polygones) . ";\n", 273 $this->_background, 274 $this->_x, 275 $this->_y, 276 sha1(mt_rand() . mt_rand() . mt_rand() . mt_rand() . mt_rand() . mt_rand() . mt_rand())); 277 278 $jsfiles = array( 279 'Init.js', 280 'Renderer.js', 281 'CanvasDriver.js', 282 'PngDriver.js', 283 'SvgDriver.js', 284 'MouseEventGenerator.js', 285 'RotateAnimationEventGenerator.js', 286 'Toolbar.js', 287 'Base64.js', 288 'Image3D.js', 289 'Startup.js'); 290 291 return str_replace($identifiers, 292 $replacements, 293 implode("\n\n", 294 array_map(create_function('$jsfile', 295 (is_dir(dirname(__FILE__) . '/../../../data/DynamicCanvas')) 296 ? ('return file_get_contents(dirname(__FILE__) . "/../../../data/DynamicCanvas/" . $jsfile);') 297 : ('return file_get_contents("@data_dir@/Image_3D/data/DynamicCanvas/" . $jsfile);')), 298 $jsfiles))); 299 } 300 301 /** 302 * Save all the gathered information to a html file 303 * 304 * @param string $file File to write output to 305 * 306 * @return void 307 */ 308 public function save($file) 309 { 310 file_put_contents($file, $this->_getJs()); 311 } 312 313 /** 314 * Return the shading methods this output driver is capable of 315 * 316 * @return array Shading methods supported by this driver 317 */ 318 public function getSupportedShading() 319 { 320 return array(Image_3D_Renderer::SHADE_NO, Image_3D_Renderer::SHADE_FLAT); 321 } 322} 323 324?> 325