# How can I shorten this code to rotate a line segment around its center?

I have a list of line segments stored in the form:

{ {{x11,y11},{x12,y12}} , {{x21,y21},{x22,y22}} , ... , {{xn1,yn1},{xn2,yn2}} }


Now I want to rotate all of them by 90 degrees about their own centers. To do that I wrote a pure function like this

{{{0, -1}, {1, 0}}.(#[[1]] - (#[[1]] + #[[2]])/2) + (#[[1]] + #[[2]])/2,
{{0, -1}, {1, 0}}.(#[[2]] - (#[[1]] + #[[2]])/2) + (#[[1]] + #[[2]])/2} &


As you can see this is pretty lengthy compare to the simplicity of my request. But I do not have enough Mathematica experience to shorten it. So can anyone help?

-

## 4 Answers

Something along the lines of Rotate[Line[pts], angle, Mean[pts]]:

g = Graphics[Line[{{1, 1}, {2, 2}}]];
rot = l : Line[pts_] :> Rotate[l, Pi/2, Mean[pts]];

Show[g, g /. rot]


I believe that Rotate and family are Graphics/Graphics3D directives which are only processed when they are rendered. If you need to access actual rotated values of the points, you can use RotationTransform instead.

-
data = RandomReal[1, {5, 2}]


Whole rotation

Graphics[{Line[data], {Red, Rotate[Line[data], Pi/2]}}]


Single segment rotation

Graphics[{Line[data], {Red, Rotate[Line[#], Pi/2]} & /@ Partition[data, 2, 1]}]


-
This does not appear to rotate line segments around their centers, as asked by the O.P. – whuber Apr 26 '13 at 20:51
@whuber added that too – Vitaliy Kaurov Apr 26 '13 at 21:27
The third argument of Rotate (your Mean[]) isn't needed here b/c the rotation is made around the bounding box center by default, and that's the line center point – Dr. belisarius Apr 26 '13 at 23:50
@belisarius I tried that - it did not look right. They were not rotations about segment centers. – Vitaliy Kaurov Apr 27 '13 at 3:34
@belisarius yep you are right. strange that PlotRange->All did not help - which i checked. Anyway I fixed it. Did not put PlotRange there though, - he can figure it out from the comments. – Vitaliy Kaurov Apr 27 '13 at 19:16

Had Rotate[]/RotationTransform[] not been available, here's a possible alternative:

BlockRandom[SeedRandom[123, Method -> "MKL"]; (* for reproducibility *)
segs = Arrow[RandomVariate[NormalDistribution[], {5, 2, 2}]]];

Graphics[{{Blue, segs},
{Red, segs /. s_?MatrixQ :> With[{m = Mean[s]}, m + Cross[# - m] & /@ s]}}]


-

Your own formula can be refactored in a more concise form:

f1 = With[{c = +##/2}, c + (# - c).{{0, -1}, {1, 0}} & /@ {##}] &;

• +##/2 is a "trick" that here is equivalent to Mean[{#, #2}]
• the function needs to be applied with @@@ rather than /@

A shorter function can be written using Cross, similar to what J. M. used:

f2 = {+##, # - #2}/2 &[+##, Cross[# - #2]] &;


Use of either function:

lines = RandomReal[{-5, 5}, {3, 2, 2}];

Graphics[{
{Thick, Line /@ lines},
{Red, Thick, Line /@ f2 @@@ lines}
}]


-