[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 6200 - (download) (as text) (annotate)
Mon Feb 1 14:51:35 2010 UTC (10 years ago) by dpvc
File size: 5304 byte(s)
Allow formula to be point-valued (if promotePoints is 1)

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright  2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: pg/macros/parserParametricLine.pl,v 1.17 2009/06/25 23:28:44 gage Exp $
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 =head1 NAME
   18 
   19 parserParametricLine.pl - Implements Formulas that represent parametric lines.
   20 
   21 =head1 DESCRIPTION
   22 
   23 This is a Parser class that implements parametric lines as
   24 a subclass of the Formula class.  The standard ->cmp routine
   25 will work for this, provided we define the compare() function
   26 needed by the overloaded ==.  We assign the special precedence
   27 so that overloaded operations will be promoted to the ones below.
   28 
   29 Use ParametricLine(point,vector) or ParametricLine(formula)
   30 to create a ParametricLine object.  You can pass an optional
   31 additional parameter that indicated the variable to use for the
   32 parameter for the line.
   33 
   34 Usage examples:
   35 
   36   $L = ParametricLine(Point(3,-1,2),Vector(1,1,3));
   37   $L = ParametricLine([3,-1,2],[1,1,3]);
   38   $L = ParametricLine("<t,1-t,2t-3>");
   39 
   40   $p = Point(3,-1,2); $v = Vector(1,1,3);
   41   $L = ParametricLine($p,$v);
   42 
   43   $t = Formula('t'); $p = Point(3,-1,2); $v = Vector(1,1,3);
   44   $L = ParametricLine($p+$t*$v);
   45 
   46   Context()->constants->are(a=>1+pi^2); # won't guess this value
   47   $L = ParametricLine("(a,2a,-1) + t <1,a,a^2>");
   48 
   49 Then use
   50 
   51    ANS($L->cmp);
   52 
   53 to get the answer checker for $L.
   54 
   55 =cut
   56 
   57 loadMacros('MathObjects.pl');
   58 
   59 sub _parserParametricLine_init {ParametricLine::Init()}; # don't reload this file
   60 
   61 #
   62 #  Define the subclass of Formula
   63 #
   64 package ParametricLine;
   65 our @ISA = qw(Value::Formula);
   66 
   67 sub Init {
   68   my $context = $main::context{ParametricLine} = Parser::Context->getCopy("Vector");
   69   $context->{name} = "ParametricLine";
   70   $context->variables->are(t=>'Real');
   71   $context->{precedence}{ParametricLine} = $context->{precedence}{special};
   72   $context->reduction->set('(-x)-y'=>0);
   73 
   74   main::Context("ParametricLine");  ### FIXME:  probably should require author to set this explicitly
   75 
   76   main::PG_restricted_eval('sub ParametricLine {ParametricLine->new(@_)}');
   77 }
   78 
   79 sub new {
   80   my $self = shift; my $class = ref($self) || $self;
   81   my $context = (Value::isContext($_[0]) ? shift : $self->context);
   82   my ($p,$v,$line,$t);
   83   return shift if scalar(@_) == 1 && ref($_[0]) eq $class;
   84   $_[0] = $context->Package("Point")->new($context,$_[0]) if ref($_[0]) eq 'ARRAY';
   85   $_[1] = $context->Package("Vector")->new($context,$_[1]) if ref($_[1]) eq 'ARRAY';
   86   if (scalar(@_) >= 2 && Value::classMatch($_[0],'Point') &&
   87                          Value::classMatch($_[1],'Vector')) {
   88     $p = shift; $v = shift;
   89     $t = shift || $context->Package("Formula")->new($context,'t');
   90     $line = $p + $t*$v;
   91   } else {
   92     $line = $context->Package("Formula")->new($context,shift);
   93     Value::Error("Your formula doesn't look like a parametric line")
   94       unless $line->type eq 'Vector' || $line->type eq "Point";
   95     $t = shift || (keys %{$line->{variables}})[0];
   96     Value::Error("A line can't be just a constant vector") unless $t;
   97     $p = $context->Package("Point")->new($context,$line->eval($t=>0));
   98     $v = $context->Package("Vector")->new($context,$line->eval($t=>1) - $p);
   99     Value::Error("Your formula isn't linear in the variable %s",$t)
  100       unless $line == $p + $context->Package("Formula")->new($context,$t) * $v;
  101   }
  102   Value::Error("The direction vector for a parametric line can't be the zero vector")
  103     if ($v->norm == 0);
  104   $line->{p} = $p; $line->{v} = $v;
  105   $line->{isValue} = $line->{isFormula} = 1;
  106   return bless $line, $class;
  107 }
  108 
  109 =head2 $lhs == $rhs
  110 
  111  #
  112  #  Two parametric lines are equal if they have
  113  #  parallel direction vectors and either the same
  114  #  points or the vector between the points is
  115  #  parallel to the (common) direction vector.
  116  #
  117 
  118 =cut
  119 
  120 sub compare {
  121   my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_);
  122   my ($lp,$lv) = ($l->{p},$l->{v});
  123   my ($rp,$rv) = ($r->{p},$r->{v});
  124   return $lv <=> $rv unless ($lv->isParallel($rv));
  125   return 0 if $lp == $rp || $lv->isParallel($rp-$lp);
  126   return $lp <=> $rp;
  127 }
  128 
  129 sub cmp_class {'a Parametric Line'};
  130 sub showClass {shift->cmp_class};
  131 
  132 sub cmp_defaults {(
  133   shift->SUPER::cmp_defaults,
  134   showEqualErrors => 0,  # don't show problems evaluating student answer
  135   ignoreInfinity => 0,   # report infinity as an error
  136 )}
  137 
  138 #
  139 #  Report some errors that were stopped by the showEqualErrors=>0 above.
  140 #
  141 sub cmp_postprocess {
  142   my $self = shift; my $ans = shift;
  143   my $error = $self->context->{error}{message};
  144   $self->cmp_error($ans)
  145     if $error =~ m/^(Your formula (isn't linear|doesn't look)|A line can't|The direction vector)/;
  146 }
  147 
  148 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9