MathGroup Archive 1999

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

Search the Archive

[Fwd: Graphics3D[] objects clipping & PlotRange]

  • To: mathgroup at smc.vnet.net
  • Subject: [mg21179] [Fwd: [mg20976] Graphics3D[] objects clipping & PlotRange]
  • From: Hartmut Wolf <hwolf at debis.com>
  • Date: Fri, 17 Dec 1999 01:23:20 -0500 (EST)
  • Organization: debis Systemhaus
  • Sender: owner-wri-mathgroup at wolfram.com

Robert Prus schrieb:
> 
> Is there a method of clipping Graphics3D[] objects except of using PlotRange
> option?
> 
> g1=ParametricPlot3D[{u,v,Sin[u]Sin[v]},{u,-Pi,Pi},{v,-Pi,Pi}]
> g2=Show[g1,PlotRange->{{-Pi/2,Pi/2},{-Pi/2,Pi/2},{-1,1}}]
> g3=Show[g2,PlotRange->All]
> 
> I need a method of creating g2 which gives me Graphics3D[] objects clipped
> to the specified box.
> 
Dear Robert,

as far as I can see, you have to do the clipping yourself. Below I give
you a function which is good enough for your example, namely clipping
Graphics3D-objects, which stem from ParametricPlot3D, and the clipping
is done along the coordinates:

splitpoly[
    Polygon[quad_ /; Length[quad] === 4, nv_:Automatic, 
      edges_:{True, True, True, True}]] := {Polygon[Drop[quad, -1], nv, 
      Append[Drop[edges, -2], False]], 
    Polygon[Drop[RotateLeft[quad], 1], nv, Append[Drop[edges, 2],
False]]}

splitpoly[p : Polygon[trip_ /; Length[trip] === 3, ___]] := {p}

cliptst[{coordinate_, clipval_, 
        cmp : (Less | LessEqual | Greater | GreaterEqual)}][pnt_] := 
  cmp[pnt[[coordinate]], clipval]

splitquad[quad_ /; Length[quad] === 4] := {Drop[quad, -1], 
    Drop[RotateLeft[quad], 1]}

splitquad[trip_ /; Length[trip] === 3] := {trip}

stdclip[d_, p : Polygon[pts_, nv_:Automatic, edges_:{True, True,
True}]]:=
  Switch[d, {True, True, True}, p,
    {False, True, True}, 
    clip1[Polygon[RotateRight[pts], nv, RotateRight[edges]]],
    {True, False, True},
    clip1[Polygon[pts, nv, edges]],
    {True, True, False},
    clip1[Polygon[RotateLeft[pts], nv, RotateLeft[edges]]],
    {True, False, False}, 
    clip2[Polygon[RotateRight[pts], nv, RotateRight[edges]]],
    {False, True, False},
    clip2[Polygon[pts, nv, edges]],
    {False, False, True},
    clip2[Polygon[RotateLeft[pts], nv, RotateLeft[edges]]],
    {False, False, False}, {}
    ]

clip1[Polygon[{p1_, p2_, p3_}, nv_, {edg1_, edgs__}]] := 
  Polygon[{p1, clip[clipspec][p1, p2], clip[clipspec][p3, p2], p3}, 
    nv, {edg1, False, edgs}]

clip2[Polygon[{p1_, p2_, p3_}, nv_, {edgs__, edg3_}]] := 
  Polygon[{clip[clipspec][p2, p1], p2, clip[clipspec][p2, p3]}, 
    nv, {edgs, False}]

clip[{coordinate_, clipval_, _}][p_, px_] := 
  With[{s = (clipval - p[[coordinate]])/(px[[coordinate]] - 
              p[[coordinate]])}, 
    Thread[(#2 - #1)s + #1 &[p, px]]]

clip[spec_, p_Polygon, test_] := 
  Block[{clipspec = spec},
Thread[stdclip[splitquad[test],splitpoly[p]]]]

clip[obj_Graphics3D, clipspec_] := 
  obj /. p : Polygon[pts_, ___] :> 
      With[{t = cliptst[clipspec] /@ pts}, 
        Which[And @@ t, p, ! Or @@ t, Unevaluated[Sequence[]], True, 
          clip[clipspec, p, t]] ]

clip takes as first parameter a Graphics3D object (which only consists
of Polygons with 3 or 4 corners, e.g. as generated from a
ParametricPlot3D).
As second parameter it takes a clip-specification {coordinate,
clipValue, comparison}. coordinate is 1, 2 or 3 for clipping planes at
x-,y-, or z-coordinates respectively, clipValue is the coordinate value
where there is the clipping off, comparison is GreaterEqual, Greater,
Less, LessEqual, such that all parts of the graphical object are clipped
of for which comparison[coordinate, clipValue] is False.


Your example:

g1 = ParametricPlot3D[{u, v, Sin[u]Sin[v]}, {u, -Pi, Pi}, {v, -Pi, Pi}];

g2 = Show[g1, PlotRange -> {{-Pi/2, Pi/2}, {-Pi/2, Pi/2}, {-0.7, 0.7}}];

Clip the object:


Show[Fold[clip, g1, 
      Join @@ MapIndexed[{{#2[[1]], #1[[1]], GreaterEqual}, {#2[[1]],
#1[[2]],
                 LessEqual}} &, {{-Pi/2, Pi/2}, {-Pi/2, Pi/2}, {-0.7,
0.7}}]],
     PlotRange -> {{-Pi, Pi}, {-Pi, Pi}, {-1, 1}}];

PlotRange shows it's really clipped

Show[%, PlotRange -> All, ViewPoint -> {-0.4, -1.4, 1.5}];

As you will have seen, there is a little difference at the cut edges
between clipping by PlotRange and this clipping procedure: there is no
borderline drawn here. But if you want it, you can have it by negating
the falseness in clip1 and clip2.

There is also subtle difference in the rendering of the polygons at the
cut edges (if you look close at the shading). This may be "repaired"
also (merge the split triangles there); but I first would like to
improve the rendering with option PolygonIntersections -> False.

Kind regards, Hartmut


  • Prev by Date: Re: how to use NonlinearRegress w. NDSolve model?
  • Next by Date: Re: Unexpected behavior with Thread
  • Previous by thread: Re: an answer to Q: efficient in-place list elementreplacement?
  • Next by thread: Re: efficient in-place list element replacement?