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