Por si pudiera interesar, la solucion que he implementado es la siguiente:
Siendo:
.- True -> Dentro / Detrás / Derecha
.- False -> Fuera / Delante / Izquiera
Código Delphi
[-]
TMc_Punto = record
x: double;
y: double;
end;
TMc_Lista_Puntos = array of TMC_Punto;
function Posicion_relativa(Puntos_Zona: TMc_Lista_Puntos;
Punto: TMC_Punto): Boolean;
function Convert_LineaToZona(Puntos_Linea: TMc_Lista_Puntos;
Fondo: Integer; Lado: Boolean): TMc_Lista_Puntos;overload;
function Convert_LineaToZona(Puntos_Linea: TMc_Lista_Puntos;
Lado: Boolean): TMc_Lista_Puntos;overload;
function Posicion_relativa(Puntos_Zona: TMc_Lista_Puntos;
Punto: TMC_Punto): Boolean;
var
vector: TMc_Lista_Puntos;
difAngulo: array of double;
situac: boolean;
i, h, vertice: integer;
d, m, c, v, anguloTotal: double;
moduloV1: double;
moduloV2: double;
prodVectSigno: double;
begin
anguloTotal := 0;
vertice := 0;
for i := 0 to Length(Puntos_Zona) - 1 do begin
h:= i+1;
if h > Length(Puntos_Zona) - 1 then h:= 0;
if i = 0 then
begin
SetLength(vector, Length(vector) + 1); vector[i].x := Puntos_Zona[i].x - punto.x; vector[i].y := Puntos_Zona[i].y - punto.y;
end;
if (i >= 0) and (i < Length(Puntos_Zona) - 1) then
begin
Setlength(vector, Length(vector) + 1); Setlength(difAngulo, Length(difAngulo) + 1); vector[h].x := Puntos_Zona[h].x - punto.x; vector[h].y := Puntos_Zona[h].y - punto.y; end;
if ((vector[i].x = 0) and (vector[i].y = 0)) or ((vector[h].x = 0) and (vector[h].y = 0)) then vertice := 1 else
begin
prodVectSigno := (vector[i].x * vector[h].y) - (vector[i].y * vector[h].x); moduloV1 := Sqrt(Power(vector[i].x, 2) + Power(vector[i].y, 2)); moduloV2 := Sqrt(Power(vector[h].x, 2) + Power(vector[h].y, 2));
v:= (vector[i].x * vector[h].x + vector[i].y * vector[h].y); m:= (moduloV1 * moduloV2);
c:= v/m;
if (c > 1) or (c < -1) then begin
c:= Int(c)
end;
d:= ArcCos( c ); if prodVectSigno > 0 then difAngulo[i] := d else difAngulo[i] := -d;
anguloTotal := anguloTotal + difAngulo[i]; Setlength(difAngulo, length(difAngulo) + 1); end;
end;
if vertice = 1 then situac := true
else
begin
if Abs(anguloTotal) < 3 then situac := false else situac := true; end;
result := situac;
end;
function Convert_LineaToZona(Puntos_Linea: TMc_Lista_Puntos;
Fondo: Integer; Lado: Boolean): TMc_Lista_Puntos;
function Desplazam(X, Y, X1, Y1, L1, L2: double): TMC_Punto;
var
Ang: double;
sAng, cAng: double;
coordDesp: TMC_Punto;
begin
Ang := arctan2(X1 - X, Y1 - Y);
cAng := cos(Ang);
sAng := sin(Ang);
coordDesp.x := X1 + (sAng * (L1) + cAng * (L2));
coordDesp.y := Y1 + (cAng * (L1) - sAng * (L2));
result := coordDesp;
var
FPuntos_Zona: TMc_Lista_Puntos;
FPoint: TMC_Punto;
dist: Double;
i: Integer;
begin
dist := Sqrt(Power(Puntos_Linea[Length(Puntos_Linea)-1].x - Puntos_Linea[0].x, 2)
+ Power(Puntos_Linea[Length(Puntos_Linea)-1].y - Puntos_Linea[0].y, 2));
SetLength(FPuntos_Zona, Length(Puntos_Linea) + 2);
if not Lado then
begin
FPoint := Desplazam(Puntos_Linea[0].x, Puntos_Linea[0].y,
Puntos_Linea[Length(Puntos_Linea) - 1].x,
Puntos_Linea[Length(Puntos_Linea) - 1].y, -dist, Fondo);
FPuntos_Zona[0].x := Round(FPoint.x);
FPuntos_Zona[0].y := Round(FPoint.y);
for i := 1 to Length(Puntos_Linea) do FPuntos_Zona[i] := Puntos_Linea[i-1];
FPoint := Desplazam(Puntos_Linea[0].x, Puntos_Linea[0].y,
Puntos_Linea[Length(Puntos_Linea) - 1].x,
Puntos_Linea[Length(Puntos_Linea) - 1].y, 0, Fondo);
FPuntos_Zona[Length(FPuntos_Zona) - 1].x := Round(FPoint.x);
FPuntos_Zona[Length(FPuntos_Zona) - 1].y := Round(FPoint.y);
end
else
begin
FPoint := Desplazam(Puntos_Linea[0].x, Puntos_Linea[0].y,
Puntos_Linea[Length(Puntos_Linea) - 1].x,
Puntos_Linea[Length(Puntos_Linea) - 1].y, -dist, -Fondo);
FPuntos_Zona[0].x := Round(FPoint.x);
FPuntos_Zona[0].y := Round(FPoint.y);
for i := 1 to Length(Puntos_Linea) do FPuntos_Zona[i] := Puntos_Linea[i-1];
FPoint := Desplazam(Puntos_Linea[0].x, Puntos_Linea[0].y,
Puntos_Linea[Length(Puntos_Linea) - 1].x,
Puntos_Linea[Length(Puntos_Linea) - 1].y, 0, -Fondo);
FPuntos_Zona[Length(FPuntos_Zona) - 1].x := Round(FPoint.x);
FPuntos_Zona[Length(FPuntos_Zona) - 1].y := Round(FPoint.y);
end;
Result:= FPuntos_Zona;
end;
function Convert_LineaToZona(Puntos_Linea: TMc_Lista_Puntos;
Lado: Boolean): TMc_Lista_Puntos;
var
dist: Double;
begin
dist := Sqrt(Power(Puntos_Linea[Length(Puntos_Linea)-1].x - Puntos_Linea[0].x, 2)
+ Power(Puntos_Linea[Length(Puntos_Linea)-1].y - Puntos_Linea[0].y, 2));
Result:= Convert_LineaToZona(Puntos_Linea, Round(dist*50), lado);
end;
Por último para usarlas:
Código Delphi
[-]
Siendo:
.- FPuntos un array of TMC_Punto que contiene los puntos que definen la línea o bien una zona poliongal
.- Punto el punto a evaluar
.- FValorCorrecto: el valor correcto esperado de la evaluación.
function TMc_Ctrl_ZonaPoligonal.Situacion(punto: TMC_Punto): Boolean;
begin
Result:= Posicion_relativa(FPuntos, punto);
end;
function TMc_Ctrl_Lineal.Situacion(punto: TMC_Punto): Boolean;
var
FPuntos_Zona: TMc_Lista_Puntos;
begin
FPuntos_Zona:= Convert_LineaToZona(FPuntos, FValorCorrecto);
if Posicion_relativa(FPuntos_Zona, punto) then
Result:= FValorCorrecto
else
Result:= not FValorCorrecto;
end;