package com.deadtroll.util;
import java.util.ArrayList;
import java.util.List;
import com.deadtroll.model.Poligono;
import com.deadtroll.model.Ponto2d;
public class GeomUtil {
/**
* Calcula as coordenadas do ponto do "momento" t, da curva de B�zier usando os pontos
* de controle.
* @param t "Momento"
* @param pontos Array de pontos e controle
* @return coordenadas do ponto da curva
*/
public static Ponto2d bezier(float t, List<Ponto2d>pontos) {
float[] x = new float[pontos.size()];
float[] y = new float[pontos.size()];
for (int i=0; i< pontos.size(); i++) {
x[i] = pontos.get(i).getX();
y[i] = pontos.get(i).getY();
}
int n = pontos.size()-1;
Ponto2d ponto = new Ponto2d();
ponto.setX(MathUtil.calcularBernstein(x, n, t));
ponto.setY(MathUtil.calcularBernstein(y, n, t));
return ponto;
}
/**
* Calcula o ponto x do c�rculo, dados �ngulo e raio
* @param x
* @param raio
* @param angulo
* @return
*/
public static float xCirculo(float x, float raio, float angulo){
return x + (raio * (float)Math.cos(Math.PI * angulo / 180.0F));
}
/**
* Calcula o ponto y do c�rculo, dados �ngulo e raio
* @param y
* @param raio
* @param angulo
* @return
*/
public static float yCirculo(float y, float raio, float angulo){
return y + (raio * (float)Math.sin(Math.PI * angulo / 180.0F));
}
/**
* Calcula todos os pontos do c�rculo
* @param centro
* @param raio
* @param pontos
* @return
*/
public static List<Ponto2d> calcularPontosCirculo(Ponto2d centro, float raio, int pontos) {
List<Ponto2d> pontosCirculo = new ArrayList<Ponto2d>();
float incremento = 360.0F / pontos;
float grauAtual = 0;
for (int i=0; i<pontos; i++) {
float x = xCirculo(centro.getX(), raio, grauAtual);
float y = yCirculo(centro.getY(), raio, grauAtual);
pontosCirculo.add(new Ponto2d(x, y));
grauAtual += incremento;
}
return pontosCirculo;
}
/**
* Utiliza o algoritmo de paridade descrito no livro "Introdu��o � geometria computacional<br>
* de Luiz Henrique de Figueiredo e Paulo C�zar Pinto Carvalho p.31 para verificar se o
* ponto pontoScanline est� no pol�gono
* @param pontoScanline
* @param poligono
* @return
*/
public static boolean pontoEmPoligono(Ponto2d pontoScanline, Poligono poligono) {
List<Ponto2d> pontosPoligono = poligono.getPontosTransformacoes();
Ponto2d ladoPoligono[] = new Ponto2d[2];
int nIntScanline = 0;
for (int i=1; i<=pontosPoligono.size(); i++) {
ladoPoligono[0] = pontosPoligono.get(i-1);
ladoPoligono[1] = pontosPoligono.get(i<pontosPoligono.size()? i : 0);
if (ladoPoligono[1].getY() != ladoPoligono[0].getY()) {
Ponto2d pontoInterseccao = pontoInterseccaoScanline(pontoScanline, ladoPoligono);
if (pontoInterseccao != null) {
if (pontoInterseccao.getX() == pontoScanline.getX()) {
break; // ponto est� sobre lado vertical
} else {
if (pontoInterseccao.getX() > pontoScanline.getX() &&
pontoInterseccao.getY() > Math.min(ladoPoligono[0].getY(), ladoPoligono[1].getY()) &&
pontoInterseccao.getY() <= Math.max(ladoPoligono[0].getY(), ladoPoligono[1].getY())) {
nIntScanline++;
}
}
}
} else {
if (pontoScanline.getY() == ladoPoligono[0].getY() &&
pontoScanline.getX() >= Math.min(ladoPoligono[0].getX(), ladoPoligono[1].getX()) &&
pontoScanline.getX() <= Math.max(ladoPoligono[0].getX(), ladoPoligono[1].getX())) {
break; // ponto est� sobre o lado horizontal
}
}
}
if (nIntScanline %2 == 0) {
return false;
}
return true;
}
/**
* Equa��o param�trica da reta para determinar se a scanline tem ponto de intersec��o com o lado do pol�gono informado<br>
* Retorno nulo informa que n�o h� intersec��o, caso contr�rio retorna o ponto de intersec��o
*
* @param pontoScanline
* @param ladoPoligono
* @return
*/
public static Ponto2d pontoInterseccaoScanline(Ponto2d pontoScanline, Ponto2d[] ladoPoligono) {
float t = (pontoScanline.getY() - ladoPoligono[0].getY()) / (ladoPoligono[1].getY() - ladoPoligono[0].getY());
if (t >= 0.0f && t <= 1.0f) {
float xInterseccao = ladoPoligono[0].getX() + (ladoPoligono[1].getX()-ladoPoligono[0].getX())*t;
return new Ponto2d(xInterseccao, pontoScanline.getY());
}
return null;
}
}