--- loncom/xml/lonplot.pm 2008/05/19 11:49:48 1.139 +++ loncom/xml/lonplot.pm 2014/07/09 15:17:32 1.152.6.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Dynamic plot # -# $Id: lonplot.pm,v 1.139 2008/05/19 11:49:48 foxr Exp $ +# $Id: lonplot.pm,v 1.152.6.1 2014/07/09 15:17:32 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,6 +26,9 @@ # http://www.lon-capa.org/ # + + + package Apache::lonplot; use strict; @@ -57,6 +60,8 @@ BEGIN { } +=pod + ## ## Description of data structures: ## @@ -88,6 +93,8 @@ BEGIN { ## ## ################################################################### +=cut + my $max_str_len = 50; # if a label, title, xlabel, or ylabel text # is longer than this, it will be truncated. @@ -448,7 +455,7 @@ my %tic_defaults = }, ); -my @axis_edit_order = ('color','xmin','xmax','ymin','ymax','xformat', 'yformat'); +my @axis_edit_order = ('color','xmin','xmax','ymin','ymax','xformat', 'yformat', 'xzero', 'yzero'); my %axis_defaults = ( color => { @@ -496,11 +503,26 @@ my %axis_defaults = yformat => { default => 'on', test => sub {$_[0]=~/^(on|off|\d+(f|F|e|E))$/}, - description => 'X-axis number formatting', + description => 'Y-axis number formatting', edit_type => 'choice', choices => ['on', 'off', '2e', '2f'], }, - + + xzero => { + default => 'off', + test => sub {$_[0]=~/^(off|line|thick-line|dotted)$/}, + description => 'Show x-zero (y=0) axis', + edit_type => 'choice', + choices => ['off', 'line', 'thick-line', 'dotted'], + }, + + yzero => { + default => 'off', + test => sub {$_[0]=~/^(off|line|thick-line|dotted)$/}, + description => 'Show y-zero (x=0) axis', + edit_type => 'choice', + choices => ['off', 'line', 'thick-line', 'dotted'], + }, ); my @curve_edit_order = ('color','name','linestyle','linewidth','linetype','pointtype','pointsize','limit'); @@ -757,6 +779,7 @@ sub get_font { $selected_font = $font_properties{$Apache::lonplot::plot{'fontface'}}; } if ($target eq 'tex' && defined($Apache::lonplot::plot{'texfont'})) { +# $selected_font = $font_properties{'classic'}; $size = $Apache::lonplot::plot{'texfont'}; } return ($size, $selected_font); @@ -819,6 +842,13 @@ sub parse_label { return $result; } +# +# Note that there are severe restrictions on font selection in the +# ps driver now. later in life Gnuplot is supposed to support +# utf-8 fonts in the posts script driver. When this happens, +# the tex entries with comments that include the word +# should be changed to print the correct glyphs rather than some +# approximation or fallback of what is intended. my %lookup = ( # Greek alphabet: @@ -888,31 +918,31 @@ my %lookup = '#134' => {'tex' => '{/Text \262}', 'web' => "\x{2020}"}, '#135' => {'tex' => '{/Text \263}', 'web' => "\x{2021}"}, '#136' => {'tex' => '\\\\^', 'web' => '\\\\^'}, - '#137' => {'tex' => '{/Text \275}', 'web' => "\x{2030}"}, - '#138' => {'tex' => 'S', 'web' => "\x{160}"}, # no S-caron in ps fonts. + '#137' => {'tex' => '%o', 'web' => "\x{2030}"}, # Per Mille + '#138' => {'tex' => 'S', 'web' => "\x{160}"}, # S-Caron '#139' => {'tex' => '<', 'web' => '<'}, - '#140' => {'tex' => '{/Text \352}', 'web' => "\x{152}"}, + '#140' => {'tex' => 'AE', 'web' => "\x{152}"}, # AE ligature '#145' => {'tex' => '\140', 'web' => "\x{2018}"}, '#146' => {'tex' => '\47', 'web' => "\x{2019}"}, - '#147' => {'tex' => '{/Text \252}', 'web' => "\x{201c}"}, - '#148' => {'tex' => '{/Text \315}', 'web' => '\\"'}, + '#147' => {'tex' => '\140\140', 'web' => "\x{201c}"}, # Left " + '#148' => {'tex' => '\47\47', 'web' => '\\"'}, # Right " '#149' => {'tex' => '{/Symbol \267}', 'web' => "\x{2022}"}, - '#150' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, #Untested here en dash + '#150' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, # en dash '#151' => {'tex' => '{/Symbol \55}', 'web' => "\x{2014}"}, # em dash - '#152' => {'tex' => '~', 'web' => '~'}, - '#153' => {'tex' => '{/Text \324}', 'web' => "\x{2122}"}, # trademark + '#152' => {'tex' => '\\\\~', 'web' => '\\\\~'}, + '#153' => {'tex' => '{/Symbol \324}', 'web' => "\x{2122}"}, # trademark # Accented letters, and other furreign language glyphs. '#154' => {'tex' => 's', 'web' => "\x{161}"}, # small s-caron no ps. '#155' => {'tex' => '>', 'web' => '\76'}, # > - '#156' => {'tex' => '{/Text \372}', 'web' => "\x{153}"}, # oe ligature. - '#159', => {'tex' => 'Y', 'web' => "\x{178}"}, # Y-umlaut - can't print + '#156' => {'tex' => '{/Text \366}', 'web' => "\x{153}"}, # oe ligature. + '#159', => {'tex' => 'Y', 'web' => "\x{178}"}, # Y-umlaut - can't print '(nbsp|#160)' => {'tex' => ' ', 'web' => ' '}, # non breaking space. '(iexcl|#161)' => {'tex' => '{/Text \241}', 'web' => "\x{a1}"}, # inverted ! '(cent|#162)' => {'tex' => '{/Text \242}', 'web' => "\x{a2}"}, # Cent currency. - '(pound|#163}' => {'tex' => '{/Text \243}', 'web' => "\x{a3}"}, # GB Pound currency. - '(curren|#164)' => {'tex' => '{/Text \250}', 'web' => "\x{a4}"}, # Generic currency symb. + '(pound|#163)' => {'tex' => '{/Text \243}', 'web' => "\x{a3}"}, # GB Pound currency. + '(curren|#164)' => {'tex' => '{/ZapfDingbats \161}','web' => "\x{a4}"}, # Generic currency symb. '(yen|#165)' => {'tex' => '{/Text \245}', 'web' => "\x{a5}"}, # Yen currency. '(brvbar|#166)' => {'tex' => '{/Symbol \174}', 'web' => "\x{a6}"}, # Broken vert bar no print. '(sect|#167)' => {'tex' => '{\247}', 'web' => "\x{a7}"}, # Section symbol. @@ -921,20 +951,20 @@ my %lookup = '(ordf|#170)' => {'tex' => '{/Text \343}', 'web' => "\x{aa}"}, # Feminine ordinal. '(laquo|#171)' => {'tex' => '{/Text \253}', 'web' => "\x{ab}"}, # << quotes. '(not|#172)' => {'tex' => '\254', 'web' => "\x{ac}"}, # Logical not. - '(shy|#173)' => {'tex' => '-', 'web' => "\x{ad}"}, # soft hyphen. + '(shy|#173)' => {'tex' => '\255', 'web' => "\x{ad}"}, # soft hyphen. '(reg|#174)' => {'tex' => '{/Symbol \342}', 'web' => "\x{ae}"}, # Registered tm. - '(macr|#175)' => {'tex' => '^{-}', 'web' => "\x{af}"}, # 'naked' macron (overbar). - '(deg|#176)' => {'tex' => '{/Text \312}', 'web' => "\x{b0}"}, # Degree symbo.. + '(macr|#175)' => {'tex' => '^{\255}', 'web' => "\x{af}"}, # 'naked' macron (overbar). + '(deg|#176)' => {'tex' => '{/Text \260}', 'web' => "\x{b0}"}, # Degree symbo..` '(plusmn|#177)' => {'tex' => '{/Symbol \261}', 'web' => "\x{b1}"}, # +/- symbol. '(sup2|#178)' => {'tex' => '^2', 'web' => "\x{b2}"}, # Superscript 2. '(sup3|#179)' => {'tex' => '^3', 'web' => "\x{b3}"}, # Superscript 3. - '(acute|#180)' => {'tex' => '{/Text \302}', 'web' => "\x{b4}"}, # 'naked' acute accent. + '(acute|#180)' => {'tex' => '{/Text \222}', 'web' => "\x{b4}"}, # 'naked' acute accent. '(micro|#181)' => {'tex' => '{/Symbol \155}', 'web' => "\x{b5}"}, # Micro (small mu). '(para|#182)' => {'tex' => '{/Text \266}', 'web' => "\x{b6}"}, # Paragraph symbol. - '(middot|#183)' => {'tex' => '^.', 'web' => "\x{b7}"}, # middle dot (maybe text 267 is better)? + '(middot|#183)' => {'tex' => '\267', 'web' => "\x{b7}"}, # middle dot '(cedil|#184)' => {'tex' => '\233', 'web' => "\x{b8}"}, # 'naked' cedilla. '(sup1|#185)' => {'tex' => '^1', 'web' => "\x{b9}"}, # superscript 1. - '(ordm|#186)' => {'tex' => '\353', 'web' => "\x{ba}"}, # masculine ordinal. + '(ordm|#186)' => {'tex' => '{\260}', 'web' => "\x{ba}"}, # masculine ordinal. '(raquo|#187)', => {'tex' => '\273', 'web' => "\x{bb}"}, # Right angle quotes. '(frac14|#188)' => {'tex' => '\274', 'web' => "\x{bc}"}, # 1/4. '(frac12|#189)' => {'tex' => '\275', 'web' => "\x{bd}"}, # 1/2. @@ -979,20 +1009,20 @@ my %lookup = '(auml|#228)' => {'tex' => '\344', 'web' => "\x{e4}"}, # a umlaut '(aring|#229)' => {'tex' => '\345', 'web' => "\x{e5}"}, # a ring on top. '(aelig|#230)' => {'tex' => '\346', 'web' => "\x{e6}"}, # ae ligature. - '{ccedil|#231)' => {'tex' => '\347', 'web' => "\x{e7}"}, # C cedilla + '(ccedil|#231)' => {'tex' => '\347', 'web' => "\x{e7}"}, # C cedilla '(egrave|#232)' => {'tex' => '\350', 'web' => "\x{e8}"}, # e accent grave. '(eacute|#233)' => {'tex' => '\351', 'web' => "\x{e9}"}, # e accent acute. '(ecirc|#234)' => {'tex' => '\352', 'web' => "\x{ea}" }, # e circumflex. '(euml|#235)' => {'tex' => '\353', 'web' => "\x{eb}"}, # e umlaut. '(igrave|#236)' => {'tex' => '\354', 'web' => "\x{ec}"}, # i grave. - '(iacute|#237}' => {'tex' => '\355', 'web' => "\x{ed}"}, # i acute. - '(icirc|#238}' => {'tex' => '\356', 'web' => "\x{ee}"}, # i circumflex. + '(iacute|#237)' => {'tex' => '\355', 'web' => "\x{ed}"}, # i acute. + '(icirc|#238)' => {'tex' => '\356', 'web' => "\x{ee}"}, # i circumflex. '(iuml|#239)' => {'tex' => '\357', 'web' => "\x{ef}"}, # i umlaut. '(eth|#240)' => {'tex' => '\360', 'web' => "\x{f0}"}, # Icelandic eth. '(ntilde|#241)' => {'tex' => '\361', 'web' => "\x{f1}"}, # n tilde. '(ograve|#242)' => {'tex' => '\362', 'web' => "\x{f2}"}, # o grave. '(oacute|#243)' => {'tex' => '\363', 'web' => "\x{f3}"}, # o acute. - '(ocirc'|#244)' => {'tex' => '\364', 'web' => "\x{f4}"}, # o circumflex. + '(ocirc|#244)' => {'tex' => '\364', 'web' => "\x{f4}"}, # o circumflex. '(otilde|#245)' => {'tex' => '\365', 'web' => "\x{f5}"}, # o tilde. '(ouml|#246)' => {'tex' => '\366', 'web' => "\x{f6}"}, # o umlaut. '(divide|#247)' => {'tex' => '\367', 'web' => "\x{f7}"}, # division symbol @@ -1007,22 +1037,144 @@ my %lookup = # Latin extended A entities: - '(OElig|#338)' => {'tex' => '{/Text \352}', 'web' => "\x{152}"}, # OE ligature. - '(oelig|#339)' => {'tex' => '{/Text \372}', 'web' => "\x{153}"}, # oe ligature. + '(OElig|#338)' => {'tex' => '{/Text \326}', 'web' => "\x{152}"}, # OE ligature. + '(oelig|#339)' => {'tex' => '{/Text \366}', 'web' => "\x{153}"}, # oe ligature. '(Scaron|#352)' => {'tex' => 'S', 'web' => "\x{160}"}, # S caron no printable. '(scaron|#353)' => {'tex' => 's', 'web' => "\x{161}"}, # s caron no printable. '(Yuml|#376)' => {'tex' => 'Y', 'web' => "\x{178}"}, # Y umlaut - no printable. # Latin extended B. - '(fnof|#402)' => {'tex' =>'{/Symbol 246}', 'web' => "\x{192}"}, # f with little hook. + '(fnof|#402)' => {'tex' =>'{/Symbol \246}', 'web' => "\x{192}"}, # f with little hook. - # Standalon accents: + # Standalone accents: '(circ|#710)' => {'tex' => '^', 'web' => '^'}, # circumflex. '(tilde|#732)' => {'tex' => '~', 'web' => '~'}, # tilde. + # General punctuation. We're not able to make a distinction between + # the various length spacings in the print version. (e.g. en/em/thin). + # the various joiners will be empty strings in the print version too. + + + '(ensp|#8194)' => {'tex' => ' ', 'web' => "\x{2002}"}, # en space. + '(emsp|#8195)' => {'tex' => ' ', 'web' => "\x{2003}"}, # em space. + '(thinsp|#8201)' => {'tex' => ' ', 'web' => "\x{2009}"}, # thin space. + '(zwnj|#8204)' => {'tex' => ' ', 'web' => "\x{200c}"}, # Zero width non joiner. + '(zwj|#8205)' => {'tex' => ' ', 'web' => "\x{200d}"}, # Zero width joiner. + '(lrm|#8206)' => {'tex' => ' ', 'web' => "\x{200e}"}, # Left to right mark + '(rlm|#8207)' => {'tex' => ' ', 'web' => "\x{200f}"}, # right to left mark. + '(ndash|#8211)' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, # en dash. + '(mdash|#8212)' => {'tex' => '{/Symbol \55}', 'web' => "\x{2014}"}, # em dash. + '(lsquo|#8216)' => {'tex' => '{/Text \140}', 'web' => "\x{2018}"}, # Left single quote. + '(rsquo|#8217)' => {'tex' => '\47', 'web' => "\x{2019}"}, # Right single quote. + '(sbquo|#8218)' => {'tex' => '\54', 'web' => "\x{201a}"}, # Single low-9 quote. + '(ldquo|#8220)' => {'tex' => '\42', 'web' => "\x{201c}"}, # Left double quote. + '(rdquo|#8221)' => {'tex' => '\42', 'web' => "\x{201d}"}, # Right double quote. + '(bdquo|#8222)' => {'tex' => ',', 'web' => "\x{201e}"}, # Double low-9 quote. + '(dagger|#8224)' => {'tex' => '+', 'web' => "\x{2020}"}, # Is this a dagger I see before me now? + '(Dagger|#8225)' => {'tex' => '\261', 'web' => "\x{2021}"}, # it's handle pointing towards my heart? + '(bull|#8226)' => {'tex' => '\267', 'web' => "\x{2022}"}, # Bullet. + '(hellep|#8230)' => {'tex' => '{/Symbol \274}', 'web' => "\x{2026}"}, # Ellipses. + '(permil|#8240)' => {'tex' => '%_o', 'web' => "\x{2031}"}, # Per mille. + '(prime|#8242)' => {'tex' => '\264', 'web' => "\x{2032}"}, # Prime. + '(Prime|#8243)' => {'tex' => '{/Symbol \262}', 'web' => "\x{2033}"}, # double prime. + '(lsaquo|#8249)' => {'tex' => '<', 'web' => "\x{2039}"}, # < quote. + '(rsaquo|#8250)' => {'tex' => '\74', 'web' => "\x{203a}"}, # > quote. + '(oline|#8254)' => {'tex' => '{/Symbol \140}', 'web' => "\x{203e}"}, # Overline. + '(frasl|#8260)' => {'tex' => '/', 'web' => "\x{2044}"}, # Fraction slash. + '(euro|#8364)' => {'tex' => '{/Symbol \240}', 'web' => "\x{20ac}"}, # Euro currency. + # Letter like symbols. + + '(weierp|#8472)' => {'tex' => '{/Symbol \303}', 'web' => "\x{2118}"}, # Power set symbol + '(image|#8465)' => {'tex' => '{/Symbol \301}', 'web' => "\x{2111}"}, # Imaginary part + '(real|#8476)' => {'tex' => '{/Symbol \302}', 'web' => "\x{211c}"}, # Real part. + '(trade|#8482)' => {'tex' => '{/Symbol \344}', 'web' => "\x{2122}"}, # trademark symbol. + '(alefsym|#8501)' => {'tex' => '{/Symbol \300}', 'web' => "\x{2135}"}, # Hebrew alef. + + # Arrows of various types and directions. + '(larr|#8592)' => {'tex' => '{/Symbol \254}', 'web' => "\x{2190}"}, # <-- + '(uarr|#8593)' => {'tex' => '{/Symbol \255}', 'web' => "\x{2191}"}, # up arrow. + '(rarr|#8594)' => {'tex' => '{/Symbol \256}', 'web' => "\x{2192}"}, # --> + '(darr|#8595)' => {'tex' => '{/Symbol \257}', 'web' => "\x{2193}"}, # down arrow. + '(harr|#8596)' => {'tex' => '{/Symbol \253}', 'web' => "\x{2194}"}, # <--> + '(crarr|#8629)' => {'tex' => '{/Symbol \277}', 'web' => "\x{21b5}"}, # corner arrow down and right. + '(lArr|#8656)' => {'tex' => '{/Symbol \334}', 'web' => "\x{21d0}"}, # <== + '(uArr|#8657)' => {'tex' => '{/Symbol \335}', 'web' => "\x{21d1}"}, # Up double arrow. + '(rArr|#8658)' => {'tex' => '{/Symbol \336}', 'web' => "\x{21d2}"}, # ==> + '(dArr|#8659)' => {'tex' => '{/Symbol \337}', 'web' => "\x{21d3}"}, # Down double arrow. + '(hArr|#8660)' => {'tex' => '{/Symbol \333}', 'web' => "\x{21d4}"}, # <==> + + # Mathematical operators. For some of these we do the best we can in printing. + + '(forall|#8704)' => {'tex' => '{/Symbol \42}', 'web' => "\x{2200}"}, # For all. + '(part|#8706)' => {'tex' => '{/Symbol d}', 'web' => "\x{2202}"}, # partial derivative + '(exist|#8707)' => {'tex' => '{/Symbol \44}', 'web' => "\x{2203}"}, # There exists. + '(empty|#8709)' => {'tex' => '{/Symbol \306}', 'web' => "\x{2205}"}, # Null set. + '(nabla|#8711)' => {'tex' => '{/Symbol \321}', 'web' => "\x{2207}"}, # Gradient e.g. + '(isin|#8712)' => {'tex' => '{/Symbol \316}', 'web' => "\x{2208}"}, # Element of the set. + '(notin|#8713)' => {'tex' => '{/Symbol \317}', 'web' => "\x{2209}"}, # Not an element of + '(ni|#8715)' => {'tex' => '{/Symbol \47}', 'web' => "\x{220b}"}, # Contains as a member + '(prod|#8719)' => {'tex' => '{/Symbol \325}', 'web' => "\x{220f}"}, # Product + '(sum|#8721)' => {'tex' => '{/Symbol \345}', 'web' => "\x{2211}"}, # Sum of. + '(minus|#8722)' => {'tex' => '{/Symbol \55}', 'web' => "\x{2212}"}, # - sign. + '(lowast|#8727)' => {'tex' => '*', 'web' => "\x{2217}"}, # * + '(radic|#8730)' => {'tex' => '{/Symbol \326}', 'web' => "\x{221a}"}, # Square root. + '(prop|#8733)' => {'tex' => '{/Symbol \265}', 'web' => "\x{221d}"}, # Proportional to. + '(infin|#8734)' => {'tex' => '{/Symbol \245}', 'web' => "\x{221e}"}, # Infinity. + '(ang|#8736)' => {'tex' => '{/Symbol \320}', 'web' => "\x{2220}"}, # Angle . + '(and|#8743)' => {'tex' => '{/Symbol \331}', 'web' => "\x{2227}"}, # Logical and. + '(or|#8744)' => {'tex' => '{/Symbol \332}', 'web' => "\x{2228}"}, # Logical or. + '(cap|#8745)' => {'tex' => '{/Symbol \307}', 'web' => "\x{2229}"}, # Set intersection. + '(cup|#8746)' => {'tex' => '{/Symbol \310}', 'web' => "\x{222a}"}, # Set union. + '(int|8747)' => {'tex' => '{/Symbol \362}', 'web' => "\x{222b}"}, # Integral. + + # Some gnuplot guru will have to explain to me why the next three + # require the extra slashes... else they print very funkily. + + '(there4|#8756)' => {'tex' => '{/Symbol \\\134}', 'web' => "\x{2234}"}, # Therefore triple dots. + '(sim|#8764)' => {'tex' => '\\\176', 'web' => "\x{223c}"}, # Simlar to. + '(cong|#8773)' => {'tex' => '{/Symbol \\\100}','web' => "\x{2245}"}, # Congruent to/with. + + '(asymp|#8776)' => {'tex' => '{/Symbol \273}', 'web' => "\x{2248}"}, # Asymptotic to. + '(ne|#8800)' => {'tex' => '{/Symbol \271}', 'web' => "\x{2260}"}, # not equal to. + '(equiv|#8801)' => {'tex' => '{/Symbol \272}', 'web' => "\x{2261}"}, # Equivalent to. + '(le|8804)' => {'tex' => '{/Symbol \243}', 'web' => "\x{2264}"}, # Less than or equal to. + '(ge|8805)' => {'tex' => '{/Symbol \263}', 'web' => "\x{2265}"}, # Greater than or equal to + '(sub|8834)' => {'tex' => '{/Symbol \314}', 'web' => "\x{2282}"}, # Subset of. + '(sup|8835)' => {'tex' => '{/Symbol \311}', 'web' => "\x{2283}"}, # Super set of. + '(nsub|8836)' => {'tex' => '{/Symbol \313}', 'web' => "\x{2284}"}, # not subset of. + '(sube|8838)' => {'tex' => '{/Symbol \315}', 'web' => "\x{2286}"}, # Subset or equal. + '(supe|8839)' => {'tex' => '{/Symbol \312}', 'web' => "\x{2287}"}, # Superset or equal + '(oplus|8853)' => {'tex' => '{/Symbol \305}', 'web' => "\x{2295}"}, # O with plus inside + '(otimes|8855)' => {'tex' => '{/Symbol \304}', 'web' => "\x{2297}"}, # O with times. + '(perp|8869)' => {'tex' => '{/Symbol \136}', 'web' => "\x{22a5}"}, # Perpendicular. + '(sdot|8901)' => {'tex' => '{/Symbol \227}', 'web' => "\x{22c5}"}, # Dot operator. + + # Misc. technical symbols: + + '(lceil|8698)' => {'tex' => '{/Symbol \351}', 'web' => "\x{2308}"}, # Left ceiling. + '(rceil|8969)' => {'tex' => '{/Symbol \371}', 'web' => "\x{2309}"}, # Right ceiling. + '(lfloor|8970)' => {'tex' => '{/Symbol \353}', 'web' => "\x{230a}"}, # Left floor. + '(rfloor|8971)' => {'tex' => '{/Symbol \373}', 'web' => "\x{230b}"}, # Right floor. + + # The gnuplot png font evidently does not have the big angle brackets at + # positions 0x2329, 0x232a so use ordinary brackets. + + '(lang|9001)' => {'tex' => '{/Symbol \341}', 'web' => '<'}, # Left angle bracket. + '(rang|9002)' => {'tex' => '{/Symbol \361}', 'web' => '>'}, # Right angle bracket. + + # Gemoetric shapes. + + '(loz|9674)' => {'tex' => '{/Symbol \340}', 'web' => "\x{25ca}"}, # Lozenge. + + # Misc. symbols + + '(spades|9824)' => {'tex' => '{/Symbol \252}', 'web' => "\x{2660}"}, + '(clubs|9827)' => {'tex' => '{/Symbol \247}', 'web' => "\x{2663}"}, + '(hearts|9829)' => {'tex' => '{/Symbol \251}', 'web' => "\x{2665}"}, + '(diams|9830)' => {'tex' => '{/Symbol \250}', 'web' => "\x{2666}"} ); @@ -1232,6 +1384,7 @@ sub start_function { my $function = &Apache::lonxml::get_all_text("/function",$parser, $style); $function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]); + $function=~s/\^/\*\*/gs; $curves[-1]->{'function'} = $function; } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function'); @@ -1302,7 +1455,7 @@ sub start_data { } # complain if the number of data points is not the same as # in previous sets of data. - if (($curves[-1]->{'data'}) && ($#data != $#{@{$curves[-1]->{'data'}->[0]}})){ + if (($curves[-1]->{'data'}) && ($#data != $#{$curves[-1]->{'data'}->[0]})){ &Apache::lonxml::warning ('Number of data points is not consistent with previous '. 'number of data points'); @@ -1458,6 +1611,8 @@ sub write_gnuplot_file { $gnuplot_input .= $fontsize; $gnuplot_input .= "\nset output \"/home/httpd/perl/tmp/". &unescape($filename).".eps\"\n"; + $gnuplot_input .= "set encoding iso_8859_1\n"; # Get access to extended font. + } # cartesian or polar plot? if (lc($Apache::lonplot::plot{'plottype'}) eq 'polar') { @@ -1526,8 +1681,12 @@ sub write_gnuplot_file { $gnuplot_input .= "set samples $Apache::lonplot::plot{'samples'}\n"; # title, xlabel, ylabel # titles - my $extra_space_x = ($xtics{'location'} eq 'axis') ? ' 0, -0.5 ' : ''; - my $extra_space_y = ($ytics{'location'} eq 'axis') ? ' -0.5, 0 ' : ''; + my $offset; + if ($version >= 4.4) { + $offset = 'offset '; + } + my $extra_space_x = ($xtics{'location'} eq 'axis') ? ' '.$offset.'0, -0.5 ' : ''; + my $extra_space_y = ($ytics{'location'} eq 'axis') ? ' '.$offset.'-0.5, 0 ' : ''; if ($target eq 'tex') { $gnuplot_input .= "set title \"$title\" font \"".$font_properties->{'printname'}.",".$fontsize."pt\"\n" if (defined($title)) ; @@ -1544,20 +1703,36 @@ sub write_gnuplot_file { $gnuplot_input .= ( $xtics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$xtics{'start'}, "; $gnuplot_input .= "$xtics{'increment'}, "; - $gnuplot_input .= "$xtics{'end'}\n"; + $gnuplot_input .= "$xtics{'end'} "; + if ($target eq 'tex') { + $gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso 8859-1 enc. + } + $gnuplot_input .= "\n"; if ($xtics{'minorfreq'} != 0) { $gnuplot_input .= "set mxtics ".$xtics{'minorfreq'}."\n"; } + } else { + if ($target eq 'tex') { + $gnuplot_input .= 'set xtics font "Helvetica,22"'."\n"; # needed in iso 8859-1 enc + } } if (%ytics) { $gnuplot_input .= "set ytics $ytics{'location'} "; $gnuplot_input .= ( $ytics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$ytics{'start'}, "; $gnuplot_input .= "$ytics{'increment'}, "; - $gnuplot_input .= "$ytics{'end'}\n"; + $gnuplot_input .= "$ytics{'end'} "; + if ($target eq 'tex') { + $gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso-8859-1 encoding. + } + $gnuplot_input .= "\n"; if ($ytics{'minorfreq'} != 0) { $gnuplot_input .= "set mytics ".$ytics{'minorfreq'}."\n"; } + } else { + if ($target eq 'tex') { + $gnuplot_input .= 'set ytics font "Helvetica,22"'."\n"; # Needed for iso 8859-1 enc. + } } # axis if (%axis) { @@ -1579,6 +1754,26 @@ sub write_gnuplot_file { } $gnuplot_input .= "set xrange \[$axis{'xmin'}:$axis{'xmax'}\]\n"; $gnuplot_input .= "set yrange \[$axis{'ymin'}:$axis{'ymax'}\]\n"; + if ($axis{'xzero'} ne 'off') { + $gnuplot_input .= "set xzeroaxis "; + if ($axis{'xzero'} eq 'line' || $axis{'xzero'} eq 'thick-line') { + $gnuplot_input .= "lt -1 "; + if ($axis{'xzero'} eq 'thick-line') { + $gnuplot_input .= "lw 3 "; + } + } + $gnuplot_input .= "\n"; + } + if ($axis{'yzero'} ne 'off') { + $gnuplot_input .= "set yzeroaxis "; + if ($axis{'yzero'} eq 'line' || $axis{'yzero'} eq 'thick-line') { + $gnuplot_input .= "lt -1 "; + if ($axis{'yzero'} eq 'thick-line') { + $gnuplot_input .= "lw 3 "; + } + } + $gnuplot_input .= "\n"; + } } # Key if (%key) { @@ -1867,3 +2062,118 @@ sub insert_data { __END__ +=head1 NAME + +Apache::lonplot.pm + +=head1 SYNOPSIS + +XML-based plotter of graphs + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + + +=head1 SUBROUTINES (parsing and edit rendering) + +=over + +=item start_gnuplot() + +=item end_gnuplot() + +=item start_xtics() + +=item end_xtics() + +=item start_ytics() + +=item end_ytics() + +=item get_font() + +=item start_key() + +=item end_key() + +=item parse_label() + +=item replace_entities() + +=item start_title() + +=item end_title() + +=item start_xlabel() + +=item end_xlabel() + +=item start_ylabel() + +=item end_label() + +=item start_curve() + +=item end_curve() + +=item start_function() + +=item end_function() + +=item start_data() + +=item end_data() + +=item start_axis() + +=item end_axis + +=back + +=head1 SUBROUTINES (Utility) + +=over + +=item set_defaults() + +=item get_attributes() + +=item write_gnuplot_file() + +=item check_inputs() + +=item edit_attributes() + +=back + +=head1 SUBROUTINES (Insertion functions for editing plots) + +=over + +=item insert_gnuplot() + +=item insert_tics() + +=item insert_xtics() + +=item insert_key() + +=item insert_axis() + +=item insert_title() + +=item insert_xlabel() + +=item insert_ylabel() + +=item insert_label() + +=item insert_curve() + +=item insert_function() + +=item insert_data() + +=back + +=cut