rotate an image

hello!
I have two questions for whoever can help me... I have been searching in the forum and I think that there is no easy solution to my problem, but I will ask anyway. Here are my doubts:

- I have an image made up by a 2D crystal lattice points (see image attached). I would like to rotate the lattice, the points, about the origin at an angle that I decide, which can change. Is there an easy way to do it?

- I would like to 'mirror' the same image not about an axis, but about a line that passes through the origin at, say, 30ยบ, and I would like to be able to change the angle of this mirroring line... Is this possible?

You're in luck. Check out the wikipedia page .http://en.wikipedia.org/wiki/Rotation_matrix Basically you get a 2*2 matrix for a specific rotation Angle and matrix multiply by a 2*N matrix containing the x,y coords for the points. The result gives you the new points. You'll have to put the x, y vals into a 2 column wave with N rows. Then transpose the matrix. Then multiply the transform matrix by the 2*N coord matrix.
No doubt there'll be an inbuilt transform to do the same thing.

Wrt to the mirroring, that should be straightforward as well.
Following on Andy's suggestions, you might look in to the matrix operations for point groups ...

http://en.wikipedia.org/wiki/Molecular_symmetry

.. and equivalent hard copy resources. Once you express your lattice as a [x, y] vector matrix, on hand the proper matrix operation, you can do any form of symmetry operation you want using the MatrixOp abilities in Igor Pro.

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
Anna,

Try this. It performs "unitful" rotations (i.e., respecting the x and y scaling) about (0,0). If you want to rotate about a different point, just shift your origin. The output is returned as M_rotated2D. The optional useInterp parameter alters how "jagged" the output is. Try it both ways just to see what I mean.

By the way, the output is automatically resized to preserve the number of points along each edge. The space around your image will just be set to NaN.

Function Rotate2D(w, angle, [useInterp])
Wave w          // 2D image
Variable angle  // degrees
Variable useInterp

if(ParamIsDefault(useInterp))
useInterp = 1       // default uses interpolation
endif

angle *= -pi/180    // convert to radians, negative sign for correct direction
Variable origX0 = DimOffset(w, 0)
Variable origX1 = DimOffset(w, 0)+DimDelta(w, 0)*(DimSize(w, 0)-1)
Variable origdX = DimDelta(w, 0)
Variable origY0 = DimOffset(w, 1)
Variable origY1 = DimOffset(w, 1)+DimDelta(w, 1)*(DimSize(w, 1)-1)
Variable origdY = DimDelta(w, 1)

// calculate new x's and y's of the corners
Variable xc1 = origX0*cos(angle)+origY0*sin(angle)
Variable yc1 = -origX0*sin(angle)+origY0*cos(angle)
Variable xc2 = origX0*cos(angle)+origY1*sin(angle)
Variable yc2 = -origX0*sin(angle)+origY1*cos(angle)
Variable xc3 = origX1*cos(angle)+origY0*sin(angle)
Variable yc3 = -origX1*sin(angle)+origY0*cos(angle)
Variable xc4 = origX1*cos(angle)+origY1*sin(angle)
Variable yc4 = -origX1*sin(angle)+origY1*cos(angle)

Variable x0 = min(min(xc1, xc2), min(xc3, xc4))
Variable x1 = max(max(xc1, xc2), max(xc3, xc4))
Variable y0 = min(min(yc1, yc2), min(yc3, yc4))
Variable y1 = max(max(yc1, yc2), max(yc3, yc4))

Variable rows = round(   sqrt(  ( DimSize(w, 0)*cos(angle) )^2 + ( DimSize(w, 1)*sin(angle) )^2  )   )
Variable cols = round(   sqrt(  ( DimSize(w, 0)*sin(angle) )^2 + ( DimSize(w, 1)*cos(angle) )^2  )   )
Make/D/O/N=(rows, cols) M_rotated2D
SetScale/I x, x0, x1, M_rotated2D
SetScale/I y, y0, y1, M_rotated2D

// fill the final image
if(useInterp)
MultiThread M_rotated2D = InRange(x*cos(-angle)+y*sin(-angle), origX0, origX1) && InRange(-x*sin(-angle)+y*cos(-angle), origY0, origY1) ? Interp2D(w, x*cos(-angle)+y*sin(-angle), -x*sin(-angle)+y*cos(-angle)) : NaN
else
MultiThread M_rotated2D = InRange(x*cos(-angle)+y*sin(-angle), origX0, origX1) && InRange(-x*sin(-angle)+y*cos(-angle), origY0, origY1) ? w(x*cos(-angle)+y*sin(-angle))(-x*sin(-angle)+y*cos(-angle)) : NaN
endif
End

ThreadSafe Static Function InRange(val, lim1, lim2)
Variable val, lim1, lim2

return (val >= lim1 && val < lim2) || (val < lim1 && val >= lim2)
End

Good luck,
Nick