• Create Account

### #ActualÁlvaro

Posted 15 January 2013 - 12:54 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear. Notice how the loop doesn't have any trigonometric functions at all. There are also basically no special cases.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z/std::abs(z);
}

C limited_rotation_towards(C original, C target, C max_rotation) {
C rotation = normalize(target / original);
if (rotation.real() < max_rotation.real())
return rotation.imag() > 0.0f ? max_rotation : conj(max_rotation);
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
C max_rotation(std::cos(max_angle), std::sin(max_angle));

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, max_rotation);
}
}


The output is this:
(1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-1.49012e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

### #5Álvaro

Posted 15 January 2013 - 12:53 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear. Notice how the loop doesn't have any trigonometric functions at all. There are also basically no special cases.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z/std::abs(z);
}

C limited_rotation_towards(C original, C target, C max_rotation) {
C rotation = normalize(target / original);
if (rotation.real() < max_rotation.real())
return rotation.imag() > 0.0f ? max_rotation : conj(max_rotation);
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
C max_rotation(std::cos(max_angle), std::sin(max_angle));

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, max_rotation);
}
}


The output is this:
1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-1.49012e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

### #4Álvaro

Posted 15 January 2013 - 12:53 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear. Notice how the loop doesn't have any trigonometric functions at all. There are also basically no special cases.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z/std::abs(z);
}

C limited_rotation_towards(C original, C target, C max_rotation) {
C rotation = normalize(target / original);
if (rotation.real() < max_rotation.real())
return rotation.imag() > 0.0f ? max_rotation : conj(max_rotation);
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
C max_rotation(std::cos(max_angle), std::sin(max_angle));

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, max_rotation);
}
}


The output is this:
(1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-2.08616e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

### #3Álvaro

Posted 15 January 2013 - 12:52 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear. Notice how the loop doesn't have any trigonometric functions at all. There are also basically no special cases.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float sign(float x) {
return (x > 0.0f) ? 1.0f : -1.0f;
}

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z/std::abs(z);
}

C limited_rotation_towards(C original, C target, C max_rotation) {
C rotation = normalize(target / original);
if (rotation.real() < max_rotation.real())
return C(max_rotation.real(),
sign(rotation.imag())*max_rotation.imag());
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
C max_rotation(std::cos(max_angle), std::sin(max_angle));

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, max_rotation);
}
}


The output is this:
(1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-2.08616e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

### #2Álvaro

Posted 15 January 2013 - 12:50 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float sign(float x) {
return (x > 0.0f) - (x < 0.0f);
}

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z/std::abs(z);
}

C limited_rotation_towards(C original, C target, C max_rotation) {
C rotation = normalize(target / original);
if (rotation.real() < max_rotation.real())
return C(max_rotation.real(),
sign(rotation.imag())*max_rotation.imag());
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
C max_rotation(std::cos(max_angle), std::sin(max_angle));

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, max_rotation);
}
}


The output is this:
(1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-2.08616e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

### #1Álvaro

Posted 15 January 2013 - 12:47 PM

I like to use complex numbers to do computations in 2D geometry. Applying a rotation is represented by multiplication by a complex number whose modulus is 1. If I have a vector A and I am trying to make it point towards vector B, the rotation I need to apply is B/A normalized. I can then limit that rotation to something close to 1 (1 being no rotation, since I am multiplying).

This code is in C++, but hopefully I managed to make it reasonably clear.
#include <iostream>
#include <complex>
#include <cmath>

typedef std::complex<float> C;

float sign(float x) {
return (x > 0.0f) - (x < 0.0f);
}

float const pi = std::atan(1.0f)*4.0f;

C normalize(C z) {
return z / std::abs(z);
}

C limited_rotation_towards(C original, C target, float min_cosine) {
C rotation = normalize(target / original);
if (rotation.real() < min_cosine)
return C(min_cosine,
sign(rotation.imag())*std::sqrt(1.0f-min_cosine*min_cosine));
return rotation;
}

int main() {
C z = 1.0f;
C target (-1.0f, -1.0f);
float max_angle = pi*0.125f;
float min_cosine = std::cos(max_angle);

for (int i=0; i<20; ++i) {
std::cout << z << '\n';
z *= limited_rotation_towards(z, target, min_cosine);
}
}


The output is this:
(1,0)
(0.92388,-0.382683)
(0.707107,-0.707107)
(0.382683,-0.92388)
(-2.08616e-07,-1)
(-0.382684,-0.923879)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)
(-0.707107,-0.707107)

PARTNERS