ID:170287
 
Problem description:
Okay, basically, I'm lending a hand to exadv1 here, but he's having trouble with the math issues of rotating a rectangle in Space station 13, so if any of you could give some advice/code snippets, that would be great. Thanks


-Aaron Hasley
Erm, you're not providing enough information, and you're not supplying a code, so this'll go under Developer How-To.
Is there any reason that exadv1 couldn't just use icon/Turn()?

FYI, by the way, this belongs in Developer How-To.
AZA wrote:
Problem description:
Okay, basically, I'm lending a hand to exadv1 here, but he's having trouble with the math issues of rotating a rectangle in Space station 13, so if any of you could give some advice/code snippets, that would be great. Thanks

A little context is crucial to figuring out what the heck you mean here. Just saying he's "rotating a rectangle" doesn't cut it, especially since BYOND itself has nothing that could be described simply as a rectangle.

Lummox JR
In response to Lummox JR (#3)
Yikes I had no idea he posted this!

Anywho I'll clarify the situation a bit. If I can get aronud to it maybe I'll post pictures...
NOTE: I only care about 90 degree rotations!

Basically I have a rectangle of objects on the map of say arbitrarily 5x8 objects. I need to have it rotated either clockwise or counter-clockwise. Also those objects have objects that are on it whose relative positions MUST be preserved.
Also I'm hopnig I can produce a rotation with the following effect:
If you overlay a regular rotation with its original state you would probably see a cross. I want it so that some sort of L or a rotation of it is produced. Of course this means there are 8 total cases to be analyzed but some of the 'actual' rotations should be repeats in theory.

Tell me if you need further clarification. I had a few mathematical ideas in the works but they failed and I don't have the background to do anything structured. =[
In response to Exadv1 (#4)
Exadv1 wrote:
Anywho I'll clarify the situation a bit. If I can get aronud to it maybe I'll post pictures...
NOTE: I only care about 90 degree rotations!

Basically I have a rectangle of objects on the map of say arbitrarily 5x8 objects. I need to have it rotated either clockwise or counter-clockwise. Also those objects have objects that are on it whose relative positions MUST be preserved.
Also I'm hopnig I can produce a rotation with the following effect:
If you overlay a regular rotation with its original state you would probably see a cross. I want it so that some sort of L or a rotation of it is produced.

So you need to rotate not only the positions of the objects, but also their images to match as well?

This should be doable. A few big questions to consider:

  • What is the center of rotation? A 5x8 group of objects doesn't have an exact center to work with. If the dimensions are either both odd or both even, this isn't a problem, but otherwise you'd have to offset pixels or something. (If they're both even, like in a 6x8 group, the center is actually a corner between the middle 4 icons.)

  • How will the rotated icons be stored to prevent a lot of icon generation/transmission overhead?

    Of course this means there are 8 total cases to be analyzed but some of the 'actual' rotations should be repeats in theory.

    No idea what you mean here about 8 total cases.

    Lummox JR
In response to Lummox JR (#5)
icon rotation shouldn't be an issue as I'm only dealing with 90 degree rotations so as long as the 'dir[ection]' of the objects are adjusted BYOND's internal icon thing should take care of it.

Now the 8 total cases has to deal with the cneter of rotation. This is for a spaceship so lets imagine a rectangular 5x8 spaceship.

Super-Case 1- Spaceship is going North
Case 1- Spaceship must turn right. SO what happens is we imagine an 8x8 square. The 'left' side of that square aligns with the 'left' side of the space ship. The spaceship must now rotate within the square so that the 'left' side aligns with the top. It has now turned left!
Case 2- Spaceship must turn left. Same as Case 1 except the square is aligned to hte right side and the spaceship must be rotated to be aligned.

The other cases are the spaceship facing south, west, and east.
Now theoretically you could use the same algorithm/idea for if you were using the 5 unit length side. Althouh it seems stranger...

Does that clear it up?
In response to Expert Advisor (#6)


_______P
|   b
a|
|
C_____
a  |
|
|b
|
|
P'

C is the center (the point it rotates about)
P is a part of the ship
P' is the location of the part when the ship rotates to the right 90 degree.

a and b are distances

you can calculate the new position for the part based on a, b, and the location of C. you just need to know the direction the ship is facing and you can determine the positions of all the parts of it.

to get it to work for things with even dimensions (2x2, for example), the coordinates of C wouldn't be integers because the figure isn't rotating about a particular tile, its rotating around a point between tiles.

+---+---+
|   |   |
|   |   |
+---C---+
|   |   |
|   |   |
+---+---+

it'd be rotating around the point between all the tiles, so you can just add/subtract 0.5 from the offsets of the parts and the coordinates of the center.
In response to OneFishDown (#7)
Here, made it just for you! Heh
Took me a bit, I was going about it the horrid, mind-boggeling way at first, then my brain turned on, and I came out with this simpler one.

Like the WARNING comments say, it requires a perfect square, and both locations but be on the same Z-layer.

This ONLY effects the /atom/movable atoms. (Don't forget, /mob and /obj are decendents of that.)

I use a version of this simply using one reference list, and using the \ref text macro to store the reference in the index, but here is the safer method.
proc/RotateBlock(turf/loc1, turf/loc2, dir)
if(loc1.z != loc2.z) return 0 // WARNING: Requires a 2-dimentional square.
if(dir != -1 && dir != 1 && dir != 2) return 0 // WARNING: Requires dir to be 1 (clockwise)
// -1 (counter-clockwise)
// or 2. (full turn)
var/Top = max(loc1.y, loc2.y)
var/Bottom = min(loc1.y, loc2.y)
var/Right = max(loc1.x, loc2.x)
var/Left = min(loc1.x, loc2.x)

var/Height = Top - Bottom + 1
var/Width = Right - Left + 1

if(Height != Width) return 0 // WARNING: Requires a perfect square.

var/list/Turfs = block(loc1, loc2)
var/list/RefA = list()
var/list/RefB = list()

var/Z = loc1.z
for(var/turf/T in Turfs)
var/X = T.x // Destination locations.
var/Y = T.y

var/FromLeft = T.x - Left // Relative locations.
var/FromBottom = T.y - Bottom
var/FromRight = Right - T.x
var/FromTop = Top - T.y

if(dir == 1)
X = FromBottom + Left
Y = FromRight + Bottom
else if(dir == -1)
X = FromTop + Left
Y = FromLeft + Bottom
else if(dir == 2)
X = FromRight + Left
Y = FromTop + Bottom

for(var/atom/movable/A in T)
RefA += A
RefB += locate(X, Y, Z)

for(var/I = 1 to length(RefA))
var/atom/movable/A = RefA[I]
A.loc = RefB[I]

return 1
Almost forgot, the way this works, the big object won't align the group of atoms at the north-west corner every time. It will also move every single movable atom in the block. If you want it to only move certain ones, just tinker with the "for(var/atom/movable/A in T)" loop.