Estuve trasteando con SVG hace poco y se me ocurrió hacer una libreria grafica sencilla para poder crear graficos con javascript y modificarlos dinamicamente (con DOM).
Lo primero que hice fue crear las funciones para crear rectas
Código PHP:
<g id="contenedor"></g>
Código PHP:
var contend= document.getElementById('contenedor');
function recta(x1,y1,x2,y2,color) {
this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; this.color=color;
var r=document.createElement("line");
r.setAttribute("x1", x1); r.setAttribute("y1", y1);
r.setAttribute("x2", x2); r.setAttribute("y2", y2);
r.setAttribute("style", "stroke:"+color);
this.setId=function(cual) {
this.setAttribute("id",cual);
}
return contend.appendChild(r);
}
Código PHP:
function alargar(idr) {
x1=parseInt(getAtr(idr,"x1")); x2=parseInt(getAtr(idr,"x2")); y1=parseInt(getAtr(idr,"y1")); y2=parseInt(getAtr(idr,"y2"));
avanzaX=x2-x1; avanzaY=y2-y1;
n=1000;
recta(x1-avanzaX*n, y1-avanzaY*n, x2+avanzaX*n, y2+avanzaY*n);
}
Código PHP:
function circulo(cx,cy,r,color,fill,op) {
var c=document.createElement("circle");
c.setAttribute("cx", cx);
c.setAttribute("cy", cy);
c.setAttribute("r", r);
c.setAttribute("style", "stroke: "+(color?color:"black")+"; fill:"+(fill?fill:"none")+"; opacity: "+(op==null?1:op));
return contend.appendChild(c);
}
Código PHP:
function pto(x, y, color) {
var point1= document.createElement('line'); var point2= document.createElement('line');
point1.setAttribute('x1', x-5); point2.setAttribute('x1', x-5);
point1.setAttribute('y1', y-5); point2.setAttribute('y1', y+5);
point1.setAttribute('x2', x+5); point2.setAttribute('x2', x+5);
point1.setAttribute('y2', y+5); point2.setAttribute('y2', y-5);
point1.setAttribute("stroke-width","1"); point2.setAttribute("stroke-width","1");
point1.setAttribute("style", "stroke:"+color); point2.setAttribute("style", "stroke:"+color);
contend.appendChild(point1); contend.appendChild(point2);
return [x,y];
}
Me supuse que podia obtener la intersección de dos rectas que tenia dibujadas, y marcarlas por un punto. Eso no fue complicado, es un poquito de matematicas. Extrayendo la ecuacion de la recta que pasa por dos puntos de la forma y=Mx+N por cada recta, y luego tomando las y ó las x iguales se resuelve un sistema de dos incognitas y dos ecuaciones. El punto sale perfecto. Por cierto, defini cuatro funciones tontas para auxiliarme:
Código PHP:
function getAtr(id,atr) { return document.getElementById(id).getAttribute(atr); }
function setAtr(id,atr,val) { document.getElementById(id).setAttribute(atr,val); }
function p(x,n) { return Math.pow(x,n) }
function cuad(x) { return p(x,2); }
Código PHP:
function i_r_r(id1,id2) {
var x,y,x1,x2,y1,y2,X1,X2,Y1,Y2;
x1=parseInt(getAtr(id1,"x1")); x2=parseInt(getAtr(id1,"x2")); y1=parseInt(getAtr(id1,"y1")); y2=parseInt(getAtr(id1,"y2"));
X1=parseInt(getAtr(id2,"x1")); X2=parseInt(getAtr(id2,"x2")); Y1=parseInt(getAtr(id2,"y1")); Y2=parseInt(getAtr(id2,"y2"));
x = (Y1*X2 - Y2*X1)/((X2-X1)*((y2-y1)/(x2-x1) - (Y2-Y1)/(X2-X1))) - (y1*x2 - y2*x1)/((x2-x1)*((y2-y1)/(x2-x1) - (Y2-Y1)/(X2-X1)));
y = ((y2-y1)/(x2-x1))*x + (y1*x2 - y2*x1)/(x2-x1);
return [x,y];
}
Código PHP:
rec=recta(200,300,800,500, "orange");
rec2=recta(500,200,400,600, "blue");
rec.setId("recta1");
rec2.setId("recta2");
elPto=i_r_r("recta1","recta2");
pto(elPto[0],elPto[1],"red");
Hasta ahí todo bien...
Ahora quería hacer lo mismo un poco mas complicado, intersección de recta y circunferencia.
Según las matematicas (hasta donde yo sé):
Código:
Así que en teoría es sencillo. Bueno pues en mi funcion (i_r_c) no funciona, da dos puntos bastante alejados del circulo (eso sí, pertenecen a la recta).RECTA: ((y2-y1)/(x2-x1))*x + (y1*x2 - y2*x1)/(x2-x1) = y CIRCUNFERENCIA: (x-X1)²+(y-Y1)²=R² x²+y²+Dx+Ey+F=0 siendo D=-2*X1; E=-2*Y1; F=X1²+Y1²-R² y como las y=Y y x=X sustituimos una en otra... x²+(((y2-y1)/(x2-x1))*x + (y1*x2 - y2*x1)/(x2-x1))²+Dx+E*(((y2-y1)/(x2-x1))*x + (y1*x2 - y2*x1)/(x2-x1))+F=0 ahora solo tenemos que resolver esa ecuacion, sacando unas x que satisfagan la ec: M=(y2-y1)/(x2-x1); N=(y1*x2 - y2*x1)/(x2-x1); x²+(M*x + N)²+Dx+E*(M*x + N)+F=0 x²+M²*x²+2*M*x*N+N²+Dx+E*M*x+E*N+F=0 (M²+1)*x² + (2*M*N+D+E*M)*x + (N²+E*N+F) = 0 ecuacion de 2º grado, 2 soluciones: A=(M²+1); B=(2*M*N+D+E*M); C=(N²+E*N+F); x=(-B+-sqrt(B²-4AC))/2A: x_1=(-B+sqrt(B²-4AC))/2A; x_2=(-B-sqrt(B²-4AC))/2A; y las y que correspondan ser. A x_1 le corresponde una y_1 y a x_2 le corresponde y_2 de ((y2-y1)/(x2-x1))*x + (y1*x2 - y2*x1)/(x2-x1) = y
Código PHP:
function i_r_c(idr,idc) {
var x1,x2,y1,y2,X1,Y1,R, A,B,C,D,E,F,M,N, x_1, x_2, y_1, y_2;
x1=parseInt(getAtr(idr,"x1")); x2=parseInt(getAtr(idr,"x2")); y1=parseInt(getAtr(idr,"y1")); y2=parseInt(getAtr(idr,"y2"));
X1=parseInt(getAtr(idc,"cx")); Y1=parseInt(getAtr(idc,"cy")); R=parseInt(getAtr(idc,"r"));
//C
D=-2*X1;
E=-2*Y1;
F=Math.sqrt( cuad(X1)+cuad(Y1)-cuad(R) );
//R
M=(y2-y1)/(x2-x1); //if(x2-x1==0) M=0;
N=(y1*x2 - y2*x1)/(x2-x1); //if(x2-x1==0) N=0;
// ec grad 2
A=1+cuad(M);
B=2*M*N+E*M+D;
C=cuad(N)+E*N+F;
// resolucion:
x_1= (-B+Math.sqrt(cuad(B)-4*A*C))/(2*A);
y_1=M*x_1 + N;
pto( x_1, y_1, "red");
x_2= (-B-Math.sqrt(cuad(B)-4*A*C))/(2*A);
y_2=M*x_2 + N;
pto( x_2, y_2, "red");
}
Pero el problema es que no da donde tiene que dar, da mucho mas lejos, haga lo que haga.
ejemplo:
Código PHP:
circ=circulo(300,300,150);
pto(300,300,"blue");
rec=recta(300,300,200,105, "orange");
circ.setAttribute("id","miCirc");
rec.setAttribute("id","miRec");
alargar("miRec");
var choque=i_r_c("miRec","miCirc");
Espero que hayan entendido todo, alguna duda me comentan, y si encuentran la solución, algún método alternativo, o algo que me pueda interesar ya saben.
Un saludo y gracias.

