      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 };