[system] / trunk / pg / macros / parserParametricLine.pl Repository:
ViewVC logotype

View of /trunk/pg/macros/parserParametricLine.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5441 - (download) (as text) (annotate)
Tue Aug 28 22:40:15 2007 UTC (12 years, 5 months ago) by dpvc
File size: 4448 byte(s)
Add context names for the context(s) created here.

    1 loadMacros('MathObjects.pl');
    2 
    3 sub _parserParametricLine_init {ParametricLine::Init()}; # don't reload this file
    4 
    5 =head1 DESCRIPTION
    6 
    7  ######################################################################
    8  #
    9  #  This is a Parser class that implements parametric lines as
   10  #  a subclass of the Formula class.  The standard ->cmp routine
   11  #  will work for this, provided we define the compare() function
   12  #  needed by the overloaded ==.  We assign the special precedence
   13  #  so that overloaded operations will be promoted to the ones below.
   14  #
   15  #  Use ParametricLine(point,vector) or ParametricLine(formula)
   16  #  to create a ParametricLine object.  You can pass an optional
   17  #  additional parameter that indicated the variable to use for the
   18  #  parameter for the line.
   19  #
   20  #  Usage examples:
   21  #
   22  #      $L = ParametricLine(Point(3,-1,2),Vector(1,1,3));
   23  #      $L = ParametricLine([3,-1,2],[1,1,3]);
   24  #      $L = ParametricLine("<t,1-t,2t-3>");
   25  #
   26  #      $p = Point(3,-1,2); $v = Vector(1,1,3);
   27  #      $L = ParametricLine($p,$v);
   28  #
   29  #      $t = Formula('t'); $p = Point(3,-1,2); $v = Vector(1,1,3);
   30  #      $L = ParametricLine($p+$t*$v);
   31  #
   32  #      Context()->constants->are(a=>1+pi^2); # won't guess this value
   33  #      $L = ParametricLine("(a,2a,-1) + t <1,a,a^2>");
   34  #
   35  #  Then use
   36  #
   37  #     ANS($L->cmp);
   38  #
   39  #  to get the answer checker for $L.
   40  #
   41 
   42 =cut
   43 
   44 #
   45 #  Define the subclass of Formula
   46 #
   47 package ParametricLine;
   48 our @ISA = qw(Value::Formula);
   49 
   50 sub Init {
   51   my $context = $main::context{ParametricLine} = Parser::Context->getCopy("Vector");
   52   $context->{name} = "ParametricLine";
   53   $context->variables->are(t=>'Real');
   54   $context->{precedence}{ParametricLine} = $context->{precedence}{special};
   55   $context->reduction->set('(-x)-y'=>0);
   56 
   57   main::Context("ParametricLine");  ### FIXME:  probably should require author to set this explicitly
   58 
   59   main::PG_restricted_eval('sub ParametricLine {ParametricLine->new(@_)}');
   60 }
   61 
   62 sub new {
   63   my $self = shift; my $class = ref($self) || $self;
   64   my $context = (Value::isContext($_[0]) ? shift : $self->context);
   65   my ($p,$v,$line,$t);
   66   return shift if scalar(@_) == 1 && ref($_[0]) eq $class;
   67   $_[0] = $context->Package("Point")->new($context,$_[0]) if ref($_[0]) eq 'ARRAY';
   68   $_[1] = $context->Package("Vector")->new($context,$_[1]) if ref($_[1]) eq 'ARRAY';
   69   if (scalar(@_) >= 2 && Value::classMatch($_[0],'Point') &&
   70                          Value::classMatch($_[1],'Vector')) {
   71     $p = shift; $v = shift;
   72     $t = shift || $context->Package("Formula")->new($context,'t');
   73     $line = $p + $t*$v;
   74   } else {
   75     $line = $context->Package("Formula")->new($context,shift);
   76     Value::Error("Your formula doesn't look like a parametric line")
   77       unless $line->type eq 'Vector';
   78     $t = shift || (keys %{$line->{variables}})[0];
   79     Value::Error("A line can't be just a constant vector") unless $t;
   80     $p = $context->Package("Point")->new($context,$line->eval($t=>0));
   81     $v = $context->Package("Vector")->new($context,$line->eval($t=>1) - $p);
   82     Value::Error("Your formula isn't linear in the variable %s",$t)
   83       unless $line == $p + $context->Package("Formula")->new($context,$t) * $v;
   84   }
   85   Value::Error("The direction vector for a parametric line can't be the zero vector")
   86     if ($v->norm == 0);
   87   $line->{p} = $p; $line->{v} = $v;
   88   $line->{isValue} = $line->{isFormula} = 1;
   89   return bless $line, $class;
   90 }
   91 
   92 =head3 $lhs == $rhs
   93 
   94  #
   95  #  Two parametric lines are equal if they have
   96  #  parallel direction vectors and either the same
   97  #  points or the vector between the points is
   98  #  parallel to the (common) direction vector.
   99  #
  100 
  101 =cut
  102 
  103 sub compare {
  104   my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_);
  105   my ($lp,$lv) = ($l->{p},$l->{v});
  106   my ($rp,$rv) = ($r->{p},$r->{v});
  107   return $lv <=> $rv unless ($lv->isParallel($rv));
  108   return 0 if $lp == $rp || $lv->isParallel($rp-$lp);
  109   return $lp <=> $rp;
  110 }
  111 
  112 sub cmp_class {'a Parametric Line'};
  113 sub showClass {shift->cmp_class};
  114 
  115 sub cmp_defaults {(
  116   shift->SUPER::cmp_defaults,
  117   showEqualErrors => 0,  # don't show problems evaluating student answer
  118   ignoreInfinity => 0,   # report infinity as an error
  119 )}
  120 
  121 #
  122 #  Report some errors that were stopped by the showEqualErrors=>0 above.
  123 #
  124 sub cmp_postprocess {
  125   my $self = shift; my $ans = shift;
  126   my $error = $self->context->{error}{message};
  127   $self->cmp_error($ans)
  128     if $error =~ m/^(Your formula (isn't linear|doesn't look)|A line can't|The direction vector)/;
  129 }
  130 
  131 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9