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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6200 - (view) (download) (as text)

1 : sh002i 5556 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
4 : dpvc 6200 # $CVSHeader: pg/macros/parserParametricLine.pl,v 1.17 2009/06/25 23:28:44 gage Exp $
5 : sh002i 5556 #
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 : sh002i 5553 =head1 NAME
18 : dpvc 2728
19 : sh002i 5553 parserParametricLine.pl - Implements Formulas that represent parametric lines.
20 : dpvc 2728
21 : gage 4997 =head1 DESCRIPTION
22 :    
23 : sh002i 5553 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 : dpvc 2728
29 : sh002i 5553 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 : sh002i 5555 $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 : sh002i 5553
40 : sh002i 5555 $p = Point(3,-1,2); $v = Vector(1,1,3);
41 :     $L = ParametricLine($p,$v);
42 : sh002i 5553
43 : sh002i 5555 $t = Formula('t'); $p = Point(3,-1,2); $v = Vector(1,1,3);
44 :     $L = ParametricLine($p+$t*$v);
45 : sh002i 5553
46 : sh002i 5555 Context()->constants->are(a=>1+pi^2); # won't guess this value
47 :     $L = ParametricLine("(a,2a,-1) + t <1,a,a^2>");
48 : sh002i 5553
49 :     Then use
50 :    
51 :     ANS($L->cmp);
52 :    
53 :     to get the answer checker for $L.
54 :    
55 : gage 4997 =cut
56 :    
57 : sh002i 5553 loadMacros('MathObjects.pl');
58 :    
59 :     sub _parserParametricLine_init {ParametricLine::Init()}; # don't reload this file
60 :    
61 : dpvc 2728 #
62 :     # Define the subclass of Formula
63 :     #
64 :     package ParametricLine;
65 :     our @ISA = qw(Value::Formula);
66 :    
67 : dpvc 5392 sub Init {
68 :     my $context = $main::context{ParametricLine} = Parser::Context->getCopy("Vector");
69 : dpvc 5441 $context->{name} = "ParametricLine";
70 : dpvc 5392 $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 : dpvc 2728 sub new {
80 :     my $self = shift; my $class = ref($self) || $self;
81 : dpvc 5075 my $context = (Value::isContext($_[0]) ? shift : $self->context);
82 : dpvc 2728 my ($p,$v,$line,$t);
83 :     return shift if scalar(@_) == 1 && ref($_[0]) eq $class;
84 : dpvc 5075 $_[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 : dpvc 2728 $p = shift; $v = shift;
89 : dpvc 5075 $t = shift || $context->Package("Formula")->new($context,'t');
90 : dpvc 2728 $line = $p + $t*$v;
91 :     } else {
92 : dpvc 5075 $line = $context->Package("Formula")->new($context,shift);
93 : dpvc 2728 Value::Error("Your formula doesn't look like a parametric line")
94 : dpvc 6200 unless $line->type eq 'Vector' || $line->type eq "Point";
95 : dpvc 2728 $t = shift || (keys %{$line->{variables}})[0];
96 : dpvc 2934 Value::Error("A line can't be just a constant vector") unless $t;
97 : dpvc 5075 $p = $context->Package("Point")->new($context,$line->eval($t=>0));
98 :     $v = $context->Package("Vector")->new($context,$line->eval($t=>1) - $p);
99 : dpvc 3371 Value::Error("Your formula isn't linear in the variable %s",$t)
100 : dpvc 5075 unless $line == $p + $context->Package("Formula")->new($context,$t) * $v;
101 : dpvc 2728 }
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 : sh002i 5554 =head2 $lhs == $rhs
110 : gage 4997
111 : dpvc 5392 #
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 : gage 4997
118 : dpvc 5075 =cut
119 : gage 4997
120 : dpvc 2728 sub compare {
121 : dpvc 5075 my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_);
122 : dpvc 2728 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 : dpvc 4385 sub showClass {shift->cmp_class};
131 : dpvc 2728
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 : dpvc 5392 my $error = $self->context->{error}{message};
144 : dpvc 5075 $self->cmp_error($ans)
145 : dpvc 2934 if $error =~ m/^(Your formula (isn't linear|doesn't look)|A line can't|The direction vector)/;
146 : dpvc 2728 }
147 :    
148 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9