[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