1 /* 2 Copyright 2009.2010 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph. 11 12 JSXGraph is free software: you can redistribute it and/or modify 13 it under the terms of the GNU Lesser General Public License as published by 14 the Free Software Foundation, either version 3 of the License, or 15 (at your option) any later version. 16 17 JSXGraph is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public License 23 along with JSXGraph. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 JXG.PsTricks = { 27 28 convert: function (board) { 29 var topleft = new JXG.Coords(JXG.COORDS_BY_SCREEN, [0, 0], board), 30 bottomright = new JXG.Coords(JXG.COORDS_BY_SCREEN, [board.canvasWidth, board.canvasHeight], board), 31 i, el, result = []; 32 33 result.push('\\begin{pspicture*}('+topleft.usrCoords[1]+','+bottomright.usrCoords[2]+')('+bottomright.usrCoords[1]+','+topleft.usrCoords[2]+')\n'); 34 35 for(i in board.objects) { 36 el = board.objects[i]; 37 38 if (el.visProp.visible) { 39 switch (el.elementClass) { 40 case JXG.OBJECT_CLASS_CIRCLE: 41 result.push(this.addCircle(el)); 42 break; 43 case JXG.OBJECT_CLASS_LINE: 44 result.push(this.addLine(el)); 45 break; 46 case JXG.OBJECT_CLASS_POINT: 47 result.push(this.addPoint(el)); 48 break; 49 default: 50 switch (el.type) { 51 case JXG.OBJECT_TYPE_ARC: 52 result.push(this.addArc(el)); 53 break; 54 case JXG.OBJECT_TYPE_SECTOR: 55 result.push(this.addArc(el)); 56 result.push(this.addSector(el)); 57 break; 58 case JXG.OBJECT_TYPE_POLYGON: 59 result.push(this.addPolygon(el)); 60 break; 61 case JXG.OBJECT_TYPE_ANGLE: 62 result.push(this.addAngle(el)); 63 break; 64 } 65 break; 66 } 67 } 68 } 69 70 result.push('\\end{pspicture*}'); 71 72 return result.join('\n'); 73 }, 74 75 setArrows: function (el) { 76 var result = ''; 77 78 if(el.visProp.firstarrow && el.visProp.lastarrow) { 79 result = '{<->}'; 80 } else if (el.visProp.firstarrow) { 81 result = '{<-}'; 82 } else if (el.visProp.lastarrow) { 83 result = '{->}'; 84 } 85 86 return result; 87 }, 88 89 /** 90 * Draws a wedge. 91 * @param {String} color HTML/CSS color string. 92 * @param {Number} opacity Numbe between 0 and 1. 93 * @param {Array} midpoint x and y value of the midpoint. 94 * @param {Number} radius 95 * @param {Number} angle1 96 * @param {Number} angle2 97 */ 98 drawWedge: function (color, opacity, midpoint, radius, angle1, angle2) { 99 var result = ''; 100 101 if(color != 'none' && opacity > 0) { 102 result += "\\pswedge[linestyle=none, fillstyle=solid, fillcolor="+this.parseColor(color)+", opacity="+opacity.toFixed(5)+"]"; 103 result += "("+midpoint.join(',')+"){"+radius+"}{"+angle1+"}{"+angle2+"}\n"; 104 } 105 106 return result; 107 }, 108 109 addPoint: function (el) { 110 var result = "\\psdot[linecolor=" + this.parseColor(el.visProp.strokecolor) + ",dotstyle=", 111 face = el.normalizeFace(el.visProp.face) || 'o', 112 size = el.visProp.size > 4 ? 4 : el.visProp.size, 113 sizemap = [0, 0, '2pt 2', '5pt 2', '5pt 3']; 114 115 // TODO: size == 1 and size > 4, faces <>, ^, v, <, and > 116 117 if(face == 'x') { 118 result += "x, dotsize=" + sizemap[size]; 119 } else if(face == 'o') { 120 result += "*, dotsize="; 121 if(size == 1) { 122 result += "2pt 2"; 123 } else if(size == 2) { 124 result += "4pt 2"; 125 } else if(size == 3) { 126 result += "6pt 2"; 127 } else if(size == 4) { 128 result += "6pt 3"; 129 } 130 } else if(face == '[]') { 131 result += "square*, dotsize=" + sizemap[size]; 132 } else if(face == '+') { 133 result += "+, dotsize=" + sizemap[size]; 134 } 135 result += "]("+el.coords.usrCoords.slice(1).join(',')+")\n"; 136 result += "\\rput("+(el.coords.usrCoords[1]+15/ el.board.unitY)+","+(el.coords.usrCoords[2]+15/ el.board.unitY)+"){\\small $"+el.name+"$}\n"; 137 138 return result; 139 }, 140 141 addLine: function (el) { 142 var screenCoords1 = new JXG.Coords(JXG.COORDS_BY_USER, el.point1.coords.usrCoords, el.board), 143 screenCoords2 = new JXG.Coords(JXG.COORDS_BY_USER, el.point2.coords.usrCoords, el.board), 144 result = "\\psline[linecolor=" + this.parseColor(el.visProp.strokecolor) + ", linewidth=" +el.visProp.strokewidth+"px]"; 145 146 if(el.visProp.straightfirst || el.visProp.straightlast) { 147 JXG.Math.Geometry.calcStraight(el, screenCoords1, screenCoords2); 148 } 149 150 result += this.setArrows(el); 151 result += "("+screenCoords1.usrCoords.slice(1).join(',')+")("+screenCoords2.usrCoords.slice(2).join(',')+")\n"; 152 153 return result; 154 }, 155 156 addCircle: function (el) { 157 var radius = el.Radius(), 158 result = "\\pscircle[linecolor=" + this.parseColor(el.visProp.strokecolor) +", linewidth=" +el.visProp.strokewidth+"px"; 159 160 if(el.visProp.fillcolor != 'none' && el.visProp.fillopacity != 0) { 161 result += ", fillstyle=solid, fillcolor="+this.parseColor(el.visProp.fillcolor)+", opacity="+el.visProp.fillopacity.toFixed(5); 162 } 163 result += "]("+el.center.coords.usrCoords.slice(1).join('1')+"){"+radius+"}\n"; 164 165 return result; 166 }, 167 168 addPolygon: function (el) { 169 var result = "\\pspolygon[linestyle=none, fillstyle=solid, fillcolor="+this.parseColor(el.visProp.fillcolor)+", opacity="+el.visProp.fillopacity.toFixed(5)+"]", 170 i; 171 172 for(i = 0; i < el.vertices.length; i++) { 173 result += "("+el.vertices[i].coords.usrCoords.slice(1).join(',')+")"; 174 } 175 result += "\n"; 176 177 return result; 178 }, 179 180 addArc: function (el) { 181 var radius = el.Radius(), 182 p = { 183 coords: new JXG.Coords(JXG.COORDS_BY_USER,[el.board.canvasWidth/(el.board.unitY), el.center.coords.usrCoords[2]], el.board) 184 }, 185 angle2 = JXG.Math.Geometry.trueAngle(p, el.center, el.point2).toFixed(4), 186 angle1 = JXG.Math.Geometry.trueAngle(p, el.center, el.point3).toFixed(4), 187 result = "\\psarc[linecolor=" + this.parseColor(el.visProp.strokecolor) + ", linewidth=" +el.visProp.strokewidth+"px]"; 188 189 result += this.setArrows(el); 190 result += "("+el.center.coords.usrCoords.slice(1).join(',')+"){"+radius+"}{"+angle2+"}{"+angle1+"}\n"; 191 192 return result; 193 }, 194 195 addSector: function (el) { 196 var radius = el.Radius(), 197 p = { 198 coords: new JXG.Coords(JXG.COORDS_BY_USER, [el.board.canvasWidth / (el.board.unitY), el.point1.coords.usrCoords[2]], el.board) 199 }, 200 angle2 = JXG.Math.Geometry.trueAngle(p, el.point1, el.point2).toFixed(4), 201 angle1 = JXG.Math.Geometry.trueAngle(p, el.point1, el.point3).toFixed(4); 202 203 return this.drawWedge(el.visProp.fillcolor, el.visProp.fillopacity, el.point1.coords.usrCoords.slice(1), radius, angle2, angle1); 204 }, 205 206 addAngle: function (el) { 207 var radius = el.radius, 208 p = { 209 coords: new JXG.Coords(JXG.COORDS_BY_USER, [el.board.canvasWidth/(el.board.unitY), el.point2.coords.usrCoords[2]], el.board) 210 }, 211 angle2 = JXG.Math.Geometry.trueAngle(p, el.point2, el.point1).toFixed(4), 212 angle1 = JXG.Math.Geometry.trueAngle(p, el.point2, el.point3).toFixed(4), 213 result; 214 215 result = this.drawWedge(el.visProp.fillcolor, el.visProp.fillopacity, el.point2.coords.usrCoords.slice(1), radius, angle2, angle1); 216 217 result += "\\psarc[linecolor=" + this.parseColor(el.visProp.strokecolor) + ", linewidth=" +el.visProp.strokewidth+"px]"; 218 result += "("+el.point2.coords.usrCoords.slice(1).join(',')+"){"+radius+"}{"+angle2+"}{"+angle1+"}\n"; 219 220 return result; 221 }, 222 223 parseColor: function (color) { 224 var arr = JXG.rgbParser(color); 225 return "{[rgb]{"+arr[0]/255+","+arr[1]/255+","+arr[2]/255+"}}"; 226 } 227 };