Re: Why do these not work?
- To: mathgroup at smc.vnet.net
- Subject: [mg109762] Re: Why do these not work?
- From: "Alexander Elkins" <alexander_elkins at hotmail.com>
- Date: Sun, 16 May 2010 05:56:41 -0400 (EDT)
- References: <hse3nk$36b$1@smc.vnet.net>
(Re-posting - lost some how...) "S. B. Gray" <stevebg at ROADRUNNER.COM> wrote in message news:hse3nk$36b$1 at smc.vnet.net... > There is something about Mathematica which does not allow the first two calls to > work, and I don't know why. Can anyone give me some guidance? > > First, do I need all these things in the Module and is there a shorter > way to "localize" them? > > plane3[p1_,p2_,p3_] := > Module[{x1,y1,z1, x2,y2,z2, x3,y3,z3, iden}, > > {x1, y1, z1} = p1; > {x2, y2, z2} = p2; > {x3, y3, z3} = p3; > > iden = 1/Det[{{x1,y1,z1},{x2,y2,z2},{x3,y3,z3}}]; > (* Or 1/Det[{p1,p2,p3}] *) > > aa = iden*Det[{{ 1, y1, z1},{ 1, y2, z2},{ 1, y3, z3}}]; > bb = iden*Det[{{x1, 1, z1},{x2, 1, z2},{x3, 1, z3}}]; > cc = iden*Det[{{x1, y1, 1},{x2, y2, 1},{x3, y3, 1}}]; > Return[{aa, bb, cc}]; (* Plane: aa*x + bb*y + cc*z = 1 *) > ] The only thing truly wrong with the plane3 example is that it does not require that each point be a list of length three. Here is the simplest form to produce the result you appear to want, with no intermediate variables, so there is nothing to localize along with an assurance of only receiving input of the proper form, i.e. that each point is a list of length three: In[2]:=plane3s[p1:{_,_,_},p2:{_,_,_},p3:{_,_,_}]:= Together[Inverse@{p1,p2,p3}.{1,1,1}] If a name for each of the elements of list making up each point is needed, here is how to do that (notice that it is still not neccessary to have any intermediate values to do this): plane3n[p1:{x1_,y1_,z1_},p2:{x2_,y2_,z2_},p3:{x3_,y3_,z3_}]:= {Det@{{1,y1,z1},{1,y2,z2},{1,y3,z3}}, Det@{{x1,1,z1},{x2,1,z2},{x3,1,z3}}, Det@{{x1,y1,1},{x2,y2,1},{x3,y3,1}}}/ Det@{{x1,y1,z1},{x2,y2,z2},{x3,y3,z3}} Mathematica evaluation only take place when the input signature matches, working a bit like an implied replacement rule. The more specific the input signatures are used first. For example: In[3]:=f[1]:=Print["x is one"];f[x_Integer]:=Print["x is an integer"]; f[x_]:=Print["x=",x];f[0];f[1];f[2.] x is an integer x is one x=2. > This ReplaceAll gives the numeric answer I want: > plane3[{x1,y1,z1},{x2,y2,z2},{x3,y3,z3}] /. > {x1 -> 1, y1 -> 0, z1 -> 0, > x2 -> 0, y2 -> 1, z2 -> 0, > x3 -> 0, y3 -> 0, z3 -> 1} > {1,1,1} This works because plane3 returns a symbolic result containing symbols, all of which have a replacement value. > This ReplaceAll does not work at all: > plane3[q1,q2,q3]/.{q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}} In[4]:=plane3[q1,q2,q3]/.{q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}} During evaluation of In[4]:= Set::shape: Lists {x1$456,y1$456,z1$456} and q1 are not the same shape. >> During evaluation of In[4]:= Set::shape: Lists {x2$456,y2$456,z2$456} and q2 are not the same shape. >> During evaluation of In[4]:= Set::shape: Lists {x3$456,y3$456,z3$456} and q3 are not the same shape. >> (remaining output omitted) The example plane3 does not require the input to have the proper form, i.e. that each point must be a list of length three. As a result the plane3 example attempts access the elements which are not lists as lists when evaluated in ths case. The example plane3s input pattern does not match so that input remains unchanged when evaluated: In[5]:=plane3s[q1,q2,q3] Out[5]=plane3s[q1,q2,q3] However after ReplaceAll (/.) changes plane3s[q1,q2,q3] into plane3s[{1,0,0},{0,1,0},{0,0,1}] the result does match the input pattern for plane3s when evaluated afterwards: In[6]:=plane3s[q1,q2,q3]/.{q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}} Out[6]={1,1,1} > This ReplaceAll gives a symbolic answer that I do not want: > q1={x1,y1,z1}; q2={x2,y2,z2}; q3={x3,y3,z3}; > plane3[q1,q2,q3]/.{q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}} Both the plane3 and plane3s examples are evaluated before the replacement occurs and therefore both return symbolic results which no longer contain the symbols q1, q2 or q3. In other words, it is late to make the replacement after the evaluation has already occured. By making sure the replacement occurs first, the result is as expected: In[7]:=q1={x1,y1,z1};q2={x2,y2,z2};q3={x3,y3,z3}; In[8]:=plane3@@({q1,q2,q3}/.{q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}}) Out[8]={1,1,1} Even this works since all the replacements occur first: In[9]:={q1,q2,q3}/.{List->plane3,q1->{1,0,0},q2->{0,1,0},q3->{0,0,1}} Out[9]={1,1,1} > What is the rule? I note in ReplaceAll x/.{{x->1},{x->3},{x->7}}, > but I don't want one at a time. Using With[] avoids creating symbols in Global`* and performs the replacement before any calculations occur: In[10]:=With[{q1={1,0,0},q2={0,1,0},q3={0,0,1}},plane3[q1,q2,q3]] Out[10]={1,1,1} > Thank you for any tips. > Steve Gray > To create a package to handle Planes, Spheres, Cones, Cylinders and other 3D objects you would not evaluate any of those objects as they appear. Intersection, Draw3D, and their like would do that. Check out the Geometrica application for Mathematica for hints. And sorry, I have no experience with Geometrica. Alexander Elkins