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.

Background: consider the following snippet:

 gp := Graphics
 bill = Import["http://i.stack.imgur.com/FyojA.jpg"];
 poly1 = {{1, 0}, {.5, .86}, {-.5, .86}, {-1, 0}, {-.5, -.86}, {.5, -.86}};
 g1 = {Texture[bill], Polygon[poly1, VertexTextureCoordinates -> poly1]};
 poly2 = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
 g2 = {Texture[bill], Polygon[poly2, VertexTextureCoordinates -> poly2]};
 g1 // gp
 g2 // gp

example of output

The option VertexTextureCoordinates isn't entirely clear to me. I want to put an image with the correct ratios in the hexagon left. So for example on {{-.5,-.5},{.5,-.5},{.5,5},{-.5,.5}}. (I have not been able to get this to work although I have tried all sort of possibilities) However with the restriction that if I rescale the (coordinates of the) hexagon the image should be scaled accordingly.

EDIT-1: enter image description here Image as requested.

EDIT-2: This nicely sums up and demonstrates the answer by Heike:

 rescale1[poly_, p1_, p2_] := 
  Transpose[{Rescale[poly[[All, 1]], {p1[[1]], p2[[1]]}, {0, 1}], 
    Rescale[poly[[All, 2]], {p1[[2]], p2[[2]]}, {0, 1}]}]
 Manipulate[
  g = {Texture[bill], 
     Polygon[poly, 
      VertexTextureCoordinates -> rescale1[poly, leftbot, righttop]]} //
     Graphics,
  {leftbot, {0, 0}, {1, 1}}, {righttop, {0, 0}, {1, 1}}, 
  Initialization :> {righttop = {1, 1}}, ControlPlacement -> Bottom]

Key is the mapping between the image and vertextexture coordinates.

share|improve this question
    
Could you please use an image that is available to anyone, e.g. ExampleData[{"TestImage", "Lena"}]? Otherwise good question. –  István Zachar Jun 30 '12 at 10:51
    
Yes, you can use that image as well. Doesn't really matter. –  ndroock1 Jun 30 '12 at 10:55
2  
Yes, of course it does not matter, it is simply easier for everyone else to copy & run your example without having to manually edit it. –  István Zachar Jun 30 '12 at 11:36
    
Point taken @IstvánZachar –  ndroock1 Jun 30 '12 at 12:22
    
@ndroock: You could... I don't know, upload the image you have (captain-bill.jpg) using the built-in image uploader, and then everybody else can execute Import[(* URL for captain-bill.jpg *)]... –  J. M. Jun 30 '12 at 13:02
add comment

3 Answers 3

up vote 5 down vote accepted

As a generalisation of kguler and Verbeia's answers, you could do something like this

rescale[poly_] :=
  Module[{xrange, yrange, ratio, midp},
   xrange = Through[{Min, Max}[poly[[All, 1]]]];
   yrange = Through[{Min, Max}[poly[[All, 2]]]];
   midp = {Total[xrange], Total[yrange]}/2;
   Rescale[(# - midp) & /@ poly, 
    Max[yrange[[2]] - yrange[[1]], xrange[[2]] - xrange[[1]]]/2 {-1, 1}, {0, 1}]
   ];

Graphics[{Texture[bill], Polygon[poly1, VertexTextureCoordinates -> rescale[poly1]]}]

Mathematica graphics

rescale is basically doing the same thing as the line Rescale[poly1,{-1,1},{0,1}] in the answers above except that the range over which to rescale is calculated automatically. This means that you can use it to rescale the vertex coordinates of any polygon without having to figure out the minimum and maximum values of the coordinates first, e.g.

SeedRandom[];
poly3 = (2 # + BlockRandom[RandomReal[{-1, 1}, 2]]) & /@ poly1;
Graphics[{Texture[bill], 
  Polygon[poly1, VertexTextureCoordinates -> rescale[poly1]],
  Polygon[poly3, VertexTextureCoordinates -> rescale[poly3]]}]

Mathematica graphics

Edit

Concerning your comment, in the coordinate system used for specifying VertexTextureCoordinates, {0, 0} corresponds to the lower left corner of the image used for the texture and {1, 1} to the upper right corner. This coordinate system is cyclic with period 1 which means that for example the point {2.3, -0.8} corresponds to the same point in the image as the points {0.3, 0.2}. To align the texture with the polygon such that the points p1 and p2 (in the coordinate system of the polygon) correspond to the lower left and upper right corners of the image, you need to rescale the coordinates of the vertices of the polygon so that p1 will be mapped to {0, 0} and p2 to {1, 1}, for example by doing something like

rescale1[poly_, p1_, p2_] := Transpose[{Rescale[poly[[All, 1]], {p1[[1]], p2[[1]]}, {0, 1}],
  Rescale[poly[[All, 2]], {p1[[2]], p2[[2]]}, {0, 1}]}]

Graphics[{Texture[bill], 
  Polygon[poly1, 
   VertexTextureCoordinates -> rescale1[poly1, {-.5, -.5}, {.5, .5}]]}]

Mathematica graphics

Here I've chosen p1 == {-.5, -.5} and p2 == {.5, .5} which will centre the texture.

share|improve this answer
    
How do the VertexTextureCoordinates exactly relate to the coordinates of the image? I want to put the bottom left point of the image to the bottom left vertex of the hexagon. Leave the ratio intact. Tile from there. - If that's possible of course. –  ndroock1 Jun 30 '12 at 12:40
    
@ndroock1 I've updated my answer –  Heike Jun 30 '12 at 14:53
    
Per request in the Meta section I wait at least 24h with my accept. Once again great help. –  ndroock1 Jun 30 '12 at 18:09
    
Your rescale1 function and explanation deserve a place in the documentation. –  ndroock1 Jul 1 '12 at 16:11
add comment

Does this work?

lena=ExampleData[{"TestImage", "Lena"}];
poly1 = {{1, 0}, {.5, .86}, {-.5, .86}, {-1, 0}, {-.5, -.86}, {.5, -.86}};
scldpoly1=Rescale[poly1,{-1,1},{0,1}];
g1 = {Texture[lena],Polygon[scldpoly1,VertexTextureCoordinates -> scldpoly1]};

Graphics[g1]

enter image description here

or something like:

poly2 = {{-.5, -.5}, {.5, -.5}, {.5, .5}, {-.5, .5}}; 
Graphics[{Brown, Polygon[poly1], Texture[lena], 
Polygon[poly2, VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]}]

enter image description here

EDIT 3: For centered tiling shifting the polygon corrdinates by .5 does the centered tiling without having to use Rescale:

poly1X = poly1 - .5;
g1 = {Texture[ExampleData[{"TestImage", "Lena"}]], 
Polygon[poly1, VertexTextureCoordinates -> poly1X]};

enter image description here

Row[Graphics[{Texture[lena],Polygon[poly1, VertexTextureCoordinates -> # poly1X]}] & /@ Range[2, 5]]

enter image description here

share|improve this answer
    
This already helps but I want it on {{-.5,-.5},{.5,-.5},{.5,5},{-.5,.5}} in the hexagon. –  ndroock1 Jun 30 '12 at 11:36
    
@ndroock1 I don't understand what you are trying to get - do you want a single copy of the picture, centered on that coordinate? In that case, you need Inset. I can do up another answer if that's what you wanted. –  Verbeia Jun 30 '12 at 11:38
    
I want to know how the function works, basically. But to be specific about the case I submitted. No not a single copy. I want it tiled with the initial copy at the given coordinates. –  ndroock1 Jun 30 '12 at 12:25
    
@ndroock1, thanks... now I see.. –  kguler Jun 30 '12 at 12:27
add comment

kguler's answer is perfectly correct but I thought it worth mentioning that rescaling the Polygon itself is not necessary, only the vertices:

gp := Graphics
bill = ExampleData[{"TestImage", "Lena"}];

rawpoly = {{1, 0}, {.5, .86}, {-.5, .86}, {-1, 
    0}, {-.5, -.86}, {.5, -.86}};

poly1 = Rescale[rawpoly, {-1, 1}, {0, 1}];
g1 = {Texture[ExampleData[{"TestImage", "Lena"}]], 
   Polygon[rawpoly, VertexTextureCoordinates -> poly1]};

g1 // gp

enter image description here

The important point is that, regardless of the coordinates of the enclosing graphic, the VertexTextureCoordinates fall in a naturally rescaled unit square ({0,0} to {1,1}), and if the coordinates in this option fall outside this region, you end up with multiple tiles of the graphic, as seen in your question. If on the other hand, you rescale to a range that is smaller than the unit square, you will only show a portion of the picture but you can center the picture somewhere else in the graphic. Notice how the picture is displaced here relative to the first version.

rawpoly = {{1, 0}, {.5, .86}, {-.5, .86}, {-1, 
    0}, {-.5, -.86}, {.5, -.86}};

poly1 = Rescale[{{1, 0}, {.5, .86}, {-.5, .86}, {-1, 
     0}, {-.5, -.86}, {.5, -.86}}, {-0.5, 0.9}, {0.4, 1}];
g2 = {Texture[ExampleData[{"TestImage", "Lena"}]], 
   Polygon[rawpoly, VertexTextureCoordinates -> poly1]};
g2 // gp

enter image description here

Just for fun, proof that it was the scaling of the vertices, not the ordering, that was the issue:

g2 = {Texture[ExampleData[{"TestImage", "Lena"}]], 
   Polygon[rawpoly, 
    VertexTextureCoordinates -> RotateRight[poly1, 2]]};

enter image description here

share|improve this answer
    
This already helps but I want it on {{-.5,-.5},{.5,-.5},{.5,5},{-.5,.5}} in the hexagon. Or any set of coordinates for that matter. I still don't get it how the option works. –  ndroock1 Jun 30 '12 at 11:37
    
Ok. I am now so far that I understand that the key lies in the right application of Rescale. The doc is rather thin on that function. A lot of trial- and error-ing required I suppose. –  ndroock1 Jun 30 '12 at 11:46
    
good point. (+1) @ndroock1, I too am unclear about "on {{-.5,-.5},{.5,-.5},{.5,5},{-.5,.5}} in the hexagon"; perhaps a textured rectangle inside a hexagon? –  kguler Jun 30 '12 at 11:56
    
@kugler The example, clearly, isn't of a major importance. I do want to understand the VertexTextureCoordinates. I read the docs of course, but they are not clear to me. I want to map imported pics to tilings. –  ndroock1 Jun 30 '12 at 12:35
    
in the docs it says:Texture[obj] is equivalent to Texture[Rasterize[obj]] and will rasterize obj at the size and resolution it would normally be displayed in a notebook. The texture is rasterized before fit to the shape. You can adjust it. –  s.s.o Jun 30 '12 at 13:26
add comment

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.