Last active
June 27, 2017 18:39
-
-
Save Alynva/92ee52f733e9e311e61efab4b49d6ee5 to your computer and use it in GitHub Desktop.
Uma biblioteca de geometria, adaptada da p5.js (JavaScript) para C++.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __Geometria_Alynva__ | |
#define __Geometria_Alynva__ | |
namespace GeoA { | |
const double TWO_PI = 6.28318530717958647693; | |
const double PI = 3.14159265358979323846; | |
const double HALF_PI = 1.57079632679489661923; | |
const double QUARTER_PI = 0.7853982; | |
double random(); // [0.0 .. 1.0] | |
double random(double); // [0.0 .. double] | |
double random(double, double); // [double .. double] | |
double map(double, double, double, double, double); | |
struct Ponto { | |
double x; // Número do componente x do vetor | |
double y; // Número do componente y do vetor | |
Ponto(double px, double py):x(px), y(py) {}; | |
Ponto(Ponto* pp):x(pp->x), y(pp->y) {}; | |
Ponto():x(), y() {}; | |
}; | |
struct Vetor : public Ponto { // Uma classe para descrever um vetor de duas ou três dimensões, especificamente um vetor euclidiano (também conhecido como geométrico). | |
double z; // Número do componente z do vetor | |
Vetor(double px, double py, double pz):Ponto(px, py), z(pz) {}; // Construtores para a passagem direta ou indireta dos componentes ou para o vetor nulo. | |
Vetor(Vetor* pv):Ponto(pv->x, pv->y), z(pv->z) {}; | |
Vetor():Ponto(0, 0), z(0) {}; | |
char* toString() const; // Retorna uma representação em sequência de caracteres de um vetor v ao chamar v.toString(). Esse método é útil para registrar vetores no console. | |
Vetor* set(double, double, double); // Definem o componente x, y e z do vetor usando três variáveis separadas ou os dados de um Vetor. | |
Vetor* set(Vetor*); | |
Vetor* copy() const; // Obtém uma cópia do vetor, retorna um objeto Vetor. | |
Vetor* add(double, double, double); // Adiciona componentes x, y e z a um vetor, adiciona um vetor a outro ou adiciona dois vetores independentes juntos. A versão do método que adiciona dois vetores juntos é um método estático e retorna um objeto Vetor, os outros atuam diretamente no vetor. | |
Vetor* add(const Vetor*); | |
static Vetor* add(Vetor*, Vetor*); | |
Vetor* sub(double, double, double); // Subtrai componentes x, y e z de um vetor, subtrai um vetor de outro, ou subtrai dois vetores independentes. A versão do método que subtrai dois vetores é um método estático e retorna um objeto Vetor, os outros atuam diretamente no vetor. | |
Vetor* sub(const Vetor*); | |
static Vetor* sub(const Vetor*, const Vetor*); | |
Vetor* mult(double); // Multiplique o vetor por um escalar. | |
Vetor* div(double); // Divida o vetor por um escalar. | |
double mag(); // Calcula a magnitude (comprimento) do vetor e retorna o resultado como um double. | |
double magSq(); // Calcula a magnitude quadrada do vetor e retorna o resultado como um double. Mais rápido se o comprimento real não for necessário no caso de comparar vetores, etc. | |
double dot(Vetor*) const; // Calcula o produto interno de dois vetores. A versão do método que calcula o produto ponto de dois vetores independentes é um método estático. | |
static double dot(Vetor*, Vetor*); | |
Vetor* cross(Vetor*) const; // Calcula e retorna um vetor composto do produto cruzado entre dois vetores. Ambos os métodos estático e não estático retornam um novo objeto Vetor. | |
static Vetor* cross(Vetor*, Vetor*); | |
double dist(const Vetor*) const; // Calcula a distância euclidiana entre dois pontos (considerando ponto como um objeto vetorial). A versão do método que calcula a distância de dois pontos independentes é um método estático. | |
static double dist(const Vetor*, const Vetor*); | |
Vetor* normalize(); // Normaliza o vetor para o comprimento 1 (faça dele um vetor unitário). | |
Vetor* limit(double); // Limita a magnitude desse vetor ao valor usado no parâmetro. | |
Vetor* setMag(double); // Define a magnitude desse vetor para o valor usado no parâmetro. | |
double heading() const; // Calcula e retorna o ângulo de rotação para este vetor (apenas vetores 2D) | |
Vetor* rotate(double); // Gira o vetor por um ângulo (apenas vetores 2D), a magnitude permanece a mesma. | |
static double angleBetween(Vetor*, Vetor*); // Calcula e retorna o ângulo (em radianos) entre dois vetores. | |
static Vetor* lerp(Vetor*, Vetor*, double = 0); // Interpolar linearmente o vetor para outro vetor. | |
double* array() const; // Retorna uma representação deste vetor como um array de double. Isso é apenas para uso temporário. Se for necessário usar de qualquer outra forma, o conteúdo deve ser copiado usando o método Vetor::copy() para copiar para sua própria matriz. | |
static bool equals(Vetor*, Vetor*); // Checa a igualdade entre dois vetores. | |
static Vetor* fromAngle(double); // Cria um novo vetor 2D unitário a partir de um ângulo. | |
static Vetor* random2D(); // Cria um novo vetor 2D unitário a partir de um ângulo aleatório. | |
static Vetor* random3D(); // Cria um novo vetor 3D unitário a partir de um ângulo aleatório. | |
}; | |
class Objeto { | |
Vetor pos; | |
Vetor target; | |
Vetor vel; | |
Vetor acc; | |
double max_speed; | |
double max_force; | |
public: | |
Objeto() { | |
this->max_speed = 10; | |
this->max_force = 1; | |
} | |
Objeto* update(); | |
Objeto* behaviors(); | |
Objeto* applyForce(const Vetor*); | |
Vetor* arrive(const Vetor*); | |
Vetor* flee(const Vetor*); | |
}; | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GeoA.h" | |
double GeoA::map(double value, double start1, double stop1, double start2, double stop2) { | |
return ((value - start1) / (stop1 - start1)) * (stop2 - start2) + start2; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GeoA.h" | |
GeoA::Objeto* GeoA::Objeto::update() { | |
this->pos.add(&this->vel); | |
this->vel.add(&this->acc); | |
this->acc.mult(0); | |
return this; | |
} | |
GeoA::Objeto* GeoA::Objeto::behaviors() { | |
return this->applyForce(this->arrive(&this->target)); | |
} | |
GeoA::Objeto* GeoA::Objeto::applyForce(const Vetor* force) { | |
this->acc.add(force); | |
return this; | |
} | |
GeoA::Vetor* GeoA::Objeto::arrive(const Vetor* target) { | |
GeoA::Vetor* desired = GeoA::Vetor::sub(target, &this->pos); | |
int d = desired->mag(); | |
double speed = this->max_speed; | |
if (d < 100) | |
speed = GeoA::map(d, 0, 100, 0, this->max_speed); | |
desired->setMag(this->max_speed); | |
GeoA::Vetor* steer = GeoA::Vetor::sub(desired, &this->vel); | |
steer->limit(this->max_force); | |
return steer; | |
} | |
GeoA::Vetor* GeoA::Objeto::flee(const Vetor* target) { | |
GeoA::Vetor* desired = GeoA::Vetor::sub(target, &this->pos); | |
if (desired->mag() < 50) { | |
desired->setMag(this->max_speed); | |
desired->mult(-1); | |
GeoA::Vetor* steer = GeoA::Vetor::sub(desired, &this->vel); | |
steer->limit(this->max_force); | |
return steer; | |
} | |
return new Vetor(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GeoA.h" | |
#include <cstdlib> // srand, rand | |
#include <ctime> // time | |
double GeoA::random() { | |
srand (static_cast <unsigned> (time(NULL))); | |
return static_cast <double> (rand()) / static_cast <double> (RAND_MAX); | |
} | |
double GeoA::random(double X) { | |
srand (static_cast <unsigned> (time(NULL))); | |
return static_cast <double> (rand()) / (static_cast <double> (RAND_MAX/X)); | |
} | |
double GeoA::random(double LO, double HI) { | |
srand (static_cast <unsigned> (time(NULL))); | |
return LO + static_cast <double> (rand()) /( static_cast <double> (RAND_MAX/(HI-LO))); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "GeoA.h" | |
#include <string> // string | |
#include <cstring> // strcpy | |
#include <cmath> // mathematical functions | |
#include <iostream> // std | |
char* GeoA::Vetor::toString() const { | |
std::string str = "Objeto GeoA::Vetor : ["; | |
str += std::to_string(this->x); | |
str += ","; | |
str += std::to_string(this->y); | |
str += ","; | |
str += std::to_string(this->z); | |
str += "]"; | |
char* temp = new char[str.size()+1]; | |
strcpy(temp, str.c_str()); | |
return temp; | |
} | |
GeoA::Vetor* GeoA::Vetor::set(double px, double py, double pz) { | |
this->x = px; | |
this->y = py; | |
this->z = pz; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::set(GeoA::Vetor* pv) { | |
this->x = pv->x; | |
this->y = pv->y; | |
this->z = pv->z; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::copy() const { | |
return new GeoA::Vetor(this->x, this->y, this->z); | |
} | |
GeoA::Vetor* GeoA::Vetor::add(double px, double py, double pz) { | |
this->x += px; | |
this->y += py; | |
this->z += pz; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::add(const GeoA::Vetor* pv) { | |
this->x += pv->x; | |
this->y += pv->y; | |
this->z += pv->z; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::add(GeoA::Vetor* pv1, GeoA::Vetor* pv2) { | |
return new GeoA::Vetor(pv1->x + pv2->y, pv1->y + pv2->y, pv1->z + pv2->z); | |
} | |
GeoA::Vetor* GeoA::Vetor::sub(double px, double py, double pz) { | |
this->x -= px; | |
this->y -= py; | |
this->z -= pz; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::sub(const GeoA::Vetor* pv) { | |
this->x -= pv->x; | |
this->y -= pv->y; | |
this->z -= pv->z; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::sub(const GeoA::Vetor* pv1, const GeoA::Vetor* pv2) { | |
double x = pv2->x - pv1->x; | |
double y = pv2->y - pv1->y; | |
double z = pv2->z - pv1->z; | |
return new Vetor(x, y, z); | |
} | |
GeoA::Vetor* GeoA::Vetor::mult(double scl) { | |
this->x *= scl; | |
this->y *= scl; | |
this->z *= scl; | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::div(double scl) { | |
this->x /= scl; | |
this->y /= scl; | |
this->z /= scl; | |
return this; | |
} | |
double GeoA::Vetor::mag() { | |
return sqrt(this->magSq()); | |
} | |
double GeoA::Vetor::magSq() { | |
return (this->x * this->x + this->y * this->y + this->z * this->z); | |
} | |
double GeoA::Vetor::dot(GeoA::Vetor* pv1, GeoA::Vetor* pv2) { | |
return (pv1->x * pv2->x + pv1->y * pv2->y + pv1->z * pv2->z); | |
} | |
GeoA::Vetor* GeoA::Vetor::cross(GeoA::Vetor* pv) const { | |
double x = this->y * pv->z - this->z * pv->y; | |
double y = this->z * pv->x - this->x * pv->z; | |
double z = this->x * pv->y - this->y * pv->x; | |
return new GeoA::Vetor(x, y, z); | |
} | |
double GeoA::Vetor::dist(const GeoA::Vetor* pv) const { | |
GeoA::Vetor* temp = pv->copy()->sub(this); | |
return temp->mag(); | |
} | |
GeoA::Vetor* GeoA::Vetor::normalize() { | |
return this->mag() == 0 || this->mag() == 1 ? this : this->div(this->mag()); | |
} | |
GeoA::Vetor* GeoA::Vetor::limit(double max) { | |
double aSq = this->magSq(); | |
if (aSq > max * max) { | |
this->div(sqrt(aSq)); // normalize it | |
this->mult(max); | |
} | |
return this; | |
} | |
GeoA::Vetor* GeoA::Vetor::setMag(double mag) { | |
return this->normalize()->mult(mag); | |
} | |
double GeoA::Vetor::heading() const { | |
return atan2(this->y, this->x); | |
} | |
GeoA::Vetor* GeoA::Vetor::rotate(double a) { | |
double newHeading = this->heading() + a; | |
double mag = this->mag(); | |
this->x = cos(newHeading) * mag; | |
this->y = sin(newHeading) * mag; | |
return this; | |
} | |
double GeoA::Vetor::angleBetween(GeoA::Vetor* pv1, GeoA::Vetor* pv2) { | |
return acos(GeoA::Vetor::dot(pv1, pv2) / (pv1->mag() * pv2->mag())); | |
} | |
GeoA::Vetor* GeoA::Vetor::lerp(GeoA::Vetor* pv1, GeoA::Vetor* pv2, double amt) { | |
Vetor* target = pv1->copy(); | |
target->x += (pv2->x - pv1->x) * amt; | |
target->y += (pv2->y - pv1->y) * amt; | |
target->z += (pv2->z - pv1->z) * amt; | |
return target; | |
} | |
double* GeoA::Vetor::array() const { | |
double* data = new double[3]; | |
data[0] = this->x; | |
data[1] = this->y; | |
data[2] = this->z; | |
return data; | |
} | |
bool GeoA::Vetor::equals(GeoA::Vetor* pv1, GeoA::Vetor* pv2) { | |
return (pv1->x == pv2->x && pv1->y == pv2->y && pv1->z == pv2->z); | |
} | |
GeoA::Vetor* GeoA::Vetor::fromAngle(double angle) { | |
return new GeoA::Vetor(cos(angle), sin(angle), 0); | |
} | |
GeoA::Vetor* GeoA::Vetor::random2D() { | |
return GeoA::Vetor::fromAngle(GeoA::random() * GeoA::PI * 2);; | |
} | |
GeoA::Vetor* GeoA::Vetor::random3D() { | |
double angle = GeoA::random() * GeoA::PI * 2; | |
double vz = GeoA::random() * 2 - 1; | |
double vx = sqrt(1 - vz * vz) * cos(angle); | |
double vy = sqrt(1 - vz * vz) * sin(angle); | |
return new GeoA::Vetor(vx, vy, vz); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment