Mathematica Asked on June 25, 2021
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 Polygon
s and FilledPolygon
s, 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}}]}]
}
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:
Texture
is wrong (or at least is misleading, as graphics objects usually include primitives);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.
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:
Correct answer by Silvia on June 25, 2021
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"}]]}]
Answered by Mark McClure on June 25, 2021
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} &)]
Answered by s.s.o on June 25, 2021
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 -> [email protected]]
Answered by István Zachar on June 25, 2021
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]}]
Graphics[{texturedShape[img,Disk[{0,0},{2,1}]],Red,Disk[{0,1},1]}]
Graphics[{Red,Disk[{0,0},0.5],texturedShape[img,Rectangle[]]}]
Answered by Simon Woods on June 25, 2021
Mathematica 10 introduced Regions which make this kind of operation much easier.
img = Rasterize@
DensityPlot[Sin@x Sin@y, {x, -4, 4}, {y, -3, 3},
ColorFunction -> "BlueGreenYellow", Frame -> None, ImageSize -> 100,
PlotRangePadding -> 0];
RegionPlot[
RegionUnion[Disk[{0, 0}, {2, 2}], Disk[{0, 0}, {3.5, 0.7}]]
, PlotStyle -> Texture[img]
][[{1}]]
Answered by Mr.Wizard on June 25, 2021
As of version 12.1, we can use (yet undocumented) SurfaceAppearance["TextureShading", Texture[img]]
to texturize 2D primitives such as Disk
, Rectangle
as well as 3D primitives like Sphere
, Tube
etc.
lena = ExampleData[{"TestImage", "Lena"}];
mandrill = ExampleData[{"TestImage", "Mandrill"}];
Graphics[{SurfaceAppearance["TextureShading", Texture[ImageMultiply[lena, Green]]],
Disk[],
SurfaceAppearance["TextureShading", Texture[mandrill]],
Rectangle[{2, -3/2}, {4, 1/2}],
BoundaryDiscretizeRegion @ RegionUnion[Disk[{1, 1}], Rectangle[{3/2, 1}]]}]
Answered by kglr on June 25, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP