MathGroup Archive 2002

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: Re: PlotVectorField

  • To: mathgroup at smc.vnet.net
  • Subject: [mg34872] RE: [mg34819] Re: PlotVectorField
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
  • Date: Tue, 11 Jun 2002 05:00:39 -0400 (EDT)
  • Sender: owner-wri-mathgroup at wolfram.com

> -----Original Message-----
> From: shollis at armstrong.edu [mailto:shollis at armstrong.edu]
To: mathgroup at smc.vnet.net
> Sent: Saturday, June 08, 2002 11:22 AM
> Subject: [mg34872] [mg34819] Re: PlotVectorField
> 
> 
> I guess my original question was a bit cryptic, but Wolf's reply got
> me thinking in the right direction. Actually what I was trying to do
> was to overlay a vector field with several curves created with
> ListPlot. The points given to ListPlot typically spill out beyond the
> rectangle on which I want to plot, so I needed so way to restrict the
> plot to the desired rectangle. PlotRange is the obvious way, but it
> leads to the difficulties I was trying to describe.
> 
> Anyway, I wonder what you all think about the following fix: Instead
> of using PlotRange, I apply a ``pullback" function to the list of
> points to make sure they all lie in the rectangle I want before I give
> the list to ListPlot. The only points in the list that can possibly
> spill out of the rectangle are the first and the last. So I made the
> following functions for each edge of the rectangle a<=x<=b, c<=y<=d.
> Each one just replaces the first/last point in the list with a convex
> combination of first two/last two points in such a way that the result
> is on the edge of the rectangle.
> 
> pulla[z_,a_]:= Module[{r=(z[[1,1]]-a)/(z[[1,1]]-z[[2,1]])},
>     ReplacePart[z, r*z[[2]]+(1-r)*z[[1]], 1]];
> pullb[z_,b_]:= Module[{r=(z[[-1,1]]-b)/(z[[-1,1]]-z[[-2,1]])},
>     ReplacePart[z, r*z[[-2]]+(1-r)*z[[-1]], -1]];
> pullc[z_,c_]:= Module[{r=(z[[1,2]]-c)/(z[[1,2]]-z[[2,2]])},
>     ReplacePart[z, r*z[[2]]+(1-r)*z[[1]], 1]];
> pulld[z_,d_]:= Module[{r=(z[[-1,2]]-d)/(z[[-1,2]]-z[[-2,2]])},
>     ReplacePart[z, r*z[[-2]]+(1-r)*z[[-1]], -1]];
> 
> Then I put everything together like this:
>  
> pullback[z_?MatrixQ,{a_,b_,c_,d_}]:=Module[{zz=z},
>  If[If[If[If[If[If[If[If[zz[[1,1]]<a,
>          zz=pulla[zz,a],zz][[1,2]]<c,
>         zz=pullc[zz,c],zz][[-1,1]]>b,
>        zz=pullb[zz,b],zz][[-1,2]]>d,
>       zz=pulld[zz,d],zz][[-1,1]]<a,
>      zz=pullb[zz,a],zz][[-1,2]]<c,
>     zz=pulld[zz,c],zz][[1,1]]>b,
>    zz=pulla[zz,b],zz][[1,2]]>d,
>   zz=pullc[zz,d],zz];zz]; 
> 
> Now, pullback[pointlist, {a,b,c,d}] gives points that all lie in the
> desired rectangle and still accurately produce the curve.
> 
> If anyone has an ideas as to how this pullback function can be written
> is a more ``MC" (Mathematica-ly Correct) way, I'd appreciate your
> advice.
> 
> Cheers,
> Selwyn
> 

Selwyn,

your problem is indeed a line clipping problem, and there are good
algorithms published. Following your idea -- I don't know if this is any
better (perhaps for the error message when the precondition on z is
violated) -- we could do

clipSLine::"condition" = "special condition for line violated";

clipSLine[z_, bounds:{{a_, c_}, {d_, e_}}] := Module[{t, zr = z}, 

  If[Not[And@@Function[f,And@@Join@@(Thread[f*(#-bounds[[f]])>=0]&) /@
Drop[z,f]]/@{1,-1}],
     Message[clipSLine::"condition"]; Return[$Failed]];

  Scan[Function[f, zr[[f]] = t*z[[f]] + (1 - t)*z[[f*2]] /. 
        t -> Min[Cases[
        t /.(Solve[#1, t]&)/@ Thread[t*z[[f]]+(1-t)*z[[f*2]]== bounds[[f]]],
_?Positive, 2],
                 1]], 
       {1, -1}]; 
  zr]

f = 1 operates at the beginning, f = -1 at the end of the line. This plus
threading avoids to set up for all special cases. Although the idea seems to
be clear, coding looks somewhat obfuscated.

Test

xx=Sort[Table[Random[],{10}]]
yy=Sort[Table[Random[],{10}]]
z1=Transpose[{xx,yy}]

z = Append[Prepend[z1, {-.1, -.1}], {1.2, .95}]

{{-0.1,-0.1},{0.144956,0.0385009},{0.161918,0.0782336},{0.267873,
    0.190657},{0.377879,0.238204},{0.46315,0.368687},{0.495381,
    0.462944},{0.634783,0.486439},{0.670151,0.540077},{0.845465,
    0.806508},{0.998876,0.884466},{1.2,0.95}}


clipSLine[z, {{0, 0}, {1, 1}}]

{{0.0768622, 0.}, {0.144956, 0.0385009}, {0.161918, 0.0782336}, {0.267873, 
    0.190657}, {0.377879, 0.238204}, {0.46315, 0.368687}, {0.495381, 
    0.462944}, {0.634783, 0.486439}, {0.670151, 0.540077}, {0.845465, 
    0.806508}, {0.998876, 0.884466}, {1., 0.884832}}

--
Hartmut



  • Prev by Date: Re: how can I solve this with mathematica?
  • Next by Date: Re: Curl
  • Previous by thread: Re: PlotVectorField
  • Next by thread: RE: Re: PlotVectorField