Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The documentation for Texture states that "other filled objects" can be texturized:

Texture[obj] is a graphics directive that specifies that obj should be used as a texture on faces of polygons and other filled graphics objects.

And also:

Texture can be used in FaceForm to texture front and back faces differently.

Though I fail to apply a simple texture to any of the following objects. It seems like that "other filled objects" only include Polygons and FilledPolygons, and FaceForm does not work with those.

img = Rasterize@
   DensityPlot[Sin@x Sin@y, {x, -4, 4}, {y, -3, 3}, 
    ColorFunction -> "BlueGreenYellow", Frame -> None, 
    ImageSize -> 100, PlotRangePadding -> 0];
{
 Graphics[{Texture@img, Disk[]}],
 Graphics[{FaceForm@Texture@img, Disk[]}],
 Graphics[{Texture@img, Rectangle[]}],
 Graphics[{FaceForm@Texture@img, Rectangle[]}],

 (* Only this one works *)
 Graphics[{Texture@img, 
   Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, 
    VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}],
 Graphics[{FaceForm@Texture@img, 
   Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, 
    VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}]
 }

Mathematica graphics

Edit:

It turns out that "Applying Texture to a disk directly isn't possible" (according to Heike, thanks s.s.o. for the link). This unfortunately means that:

  1. the official documentation of Texture is wrong (or at least is misleading, as graphics objects usually include primitives);
  2. either Texture is not fully integrated with the system, as it is not applicable for such primitives as a Rectangle, which seems to be just a very specific Polygon; or Rectangle is something else and is defined some other way at the lowest level than a Polygon (maybe it is some OS-dependent object).

Frankly, it is quite hard to imagine what kept developers to include this functionality, but I must assume they had a good reason.

share|improve this question
    
I imagine that you know how to do this with ParametricPlot and PlotStyle as in the documentation for ParametricPlot? –  Mark McClure Jun 29 '12 at 15:34
    
@Mark: But any Plot is not a graphics primitive, is it? (btw, are you referring to RegionPlot?) I would like to texturize primitives, if possible. I am also aware of these threads: this and this. –  István Zachar Jun 29 '12 at 15:40
    
I don't think you can Texture primitives like Disk[], Sphere[], etc –  rm -rf Jun 29 '12 at 15:44
    
@Istvan Right. I guess I meant to say that I suspect that you know how to achieve the basic effect with ParametricPlot, not how to produce the exact primitives. Sometimes an alternative approach is of interest but, since you're a regular, I didn't think I'd bother typing up a response based on that. –  Mark McClure Jun 29 '12 at 15:45
    
@Mark: As always, I am interested in any bypass solution, please post yours if it hasn't been posted anywhere else! –  István Zachar Jun 29 '12 at 15:54

5 Answers 5

up vote 7 down vote accepted

I noticed an example in the document of Texture which used the alpha channel. So I think a disk-shape primitive may be simulated to a limited degree by mapping the image img, which has been set to 100% transparent outside of the circle, onto a rectangle-shape Polygon.

My code:

img = Rasterize[
                DensityPlot[Sin[x] Sin[y],
                            {x, -4, 4}, {y, -3, 3},
                            ColorFunction -> "BlueGreenYellow",
                            Frame -> None, ImageSize -> 100, PlotRangePadding -> 0
              ]];

imgdim = ImageDimensions[img]

alphamask = Array[
                  If[
                     Norm[{#1, #2} - imgdim/2] < imgdim[[1]]/2,
                     1,0]&,
                  imgdim];

alphaimg = MapThread[Append, {img // ImageData, alphamask}, 2];

Graphics[{
          Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}} + .3],
          Texture[alphaimg],
          Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, 
                  VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}
                 ],
          Gray, Disk[{0, 0}, .5]
         }]

which gives result like this:

result graph

share|improve this answer
1  
Clever! I always forget that such problems can be solved by image processing tricks. –  István Zachar Jun 29 '12 at 22:00
    
@IstvánZachar but it's less effective than your fallback method, and the boundary is ugly OTL –  Silvia Jun 29 '12 at 22:13
    
Definitely the best method (+1). –  Jens Jun 29 '12 at 23:10

Here's an extension of Silvia's method of setting an alpha channel in the texture. The alpha mask is obtained directly from the shape using Rasterize, allowing the code to work with ellipses, rectangles, etc.

img = Rasterize@
   DensityPlot[Sin@x Sin@y, {x, -4, 4}, {y, -3, 3}, 
    ColorFunction -> "BlueGreenYellow", Frame -> None, 
    ImageSize -> 300, PlotRangePadding -> 0];

texturedShape[img_, shape_] := Module[{g, p, ar, i},
  g = Graphics[shape, PlotRangePadding -> 0];
  p = Polygon[
    AbsoluteOptions[g, PlotRange][[1, 
       2]] /. {{l_, r_}, {b_, t_}} :> {{l, b}, {l, t}, {r, t}, {r, 
        b}}, VertexTextureCoordinates -> {{0, 0}, {0, 1}, {1, 1}, {1, 
       0}}];
  ar = AbsoluteOptions[g, AspectRatio][[1, 2]];
  i = SetAlphaChannel[img, 
    ColorNegate@Rasterize[g, ImageSize -> ImageDimensions@img]];
  i = ImageCrop[i, 
    Round[If[ar > 1, {1/ar, 1}, {1, ar}] ImageDimensions@img]];
  {Texture[ImageData@i], p}]

The Rasterize gets its ImageDimensions from the original texture image, so I've increased the size of that to 300 to get cleaner edges.

Examples:

Graphics[{texturedShape[img,Disk[{0,0},2]],Red,Disk[{0,1},1]}]

enter image description here

Graphics[{texturedShape[img,Disk[{0,0},{2,1}]],Red,Disk[{0,1},1]}]

enter image description here

Graphics[{Red,Disk[{0,0},0.5],texturedShape[img,Rectangle[]]}]

enter image description here

share|improve this answer

My fallback method for the moment is the following: approximate a circle with a polygon, fill the latter with the texture and finally conceal the angular edge with an overlaid Circle. If the whole image is small, the number of nodes of the polygon can be further reduced. One annoying sideeffect is though that the Circle is not antialiased...

img = Rasterize@
   DensityPlot[Sin@x Sin@y, {x, -4, 4}, {y, -3, 3}, 
    ColorFunction -> "BlueGreenYellow", Frame -> None, 
    ImageSize -> 200, PlotRangePadding -> 0];
coord = Block[{n = 100}, 
   Table[{Cos[2 \[Pi] k/n], Sin[2 \[Pi] k/n]}, {k, 0, n - 1}]];
Graphics[{Texture@img, EdgeForm@None, 
  Polygon[coord, VertexTextureCoordinates -> (coord/2 + .5)], Black, 
  Thick, Circle[]}, ImageSize -> 200, Background -> GrayLevel@.9]

Mathematica graphics

share|improve this answer
    
You can replace Circle[] with Style[Circle[], Antialiasing -> True] to get the circle antialiased. (+1) –  kguler Jun 29 '12 at 21:54
    
@kguler: Strangely, this does not work on my end, no matter how hard I try. –  István Zachar Jun 29 '12 at 21:59
    
Strange... perhaps os/version/hardware differences? Suggestion was from the docs on Antialiasing. –  kguler Jun 29 '12 at 22:01
    
@kguler: I have no idea, I probably had messed up something myself, but I gave up on this for now. –  István Zachar Jul 1 '12 at 20:02

If you click the disk and check Drawing tools from the menu there is only color fill options no texture options available. Also see Heike's related answers: in math group or mathematica group mainly she states "Applying Texture to a disk directly isn't possible, but you could for example use RegionPlot with the TextureCoordinateFunction option, e.g"

img = Rasterize@
   DensityPlot[Sin@x Sin@y, {x, -4, 4}, {y, -3, 3}, 
    ColorFunction -> "BlueGreenYellow", Frame -> None, 
    ImageSize -> 100, PlotRangePadding -> 0];

RegionPlot[x^2 + y^2 < 1, {x, -1, 1}, {y, -1, 1}, 
 BoundaryStyle -> None, 
 Axes -> False, Frame -> False, 
 PlotStyle -> Directive[Opacity[1], Texture[img]], 
 TextureCoordinateFunction -> ({#1, #2} &)] 
share|improve this answer

Like RM, I've not been able to texture a Disk primitive. We can create a textured disk using ParametricPlot, however.

ParametricPlot[{r*Cos[t], r*Sin[t]}, {r, 0, 1}, {t, 0, 2 Pi},
  Mesh -> False, BoundaryStyle -> None, Axes -> False,
  PlotStyle -> {Opacity[1], 
   Texture[ExampleData[{"ColorTexture", "LightCherry"}]]}]

enter image description here

share|improve this answer
    
You will also want to look into the option TextureCoordinateFunction; for instance, compare Mark's plot with ParametricPlot[{r Cos[t], r Sin[t]}, {r, 0, 1}, {t, 0, 2 Pi}, Mesh -> False, BoundaryStyle -> None, Axes -> False, PlotStyle -> {Opacity[1], Texture[ExampleData[{"ColorTexture", "LightCherry"}]]}, TextureCoordinateFunction -> ({#4, #3} &)]. –  J. M. Jun 29 '12 at 16:17
    
Yes - In fact, I lifted that code right out of the documentation for TextureCoordinateFunction. –  Mark McClure Jun 29 '12 at 16:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.