Implementando um algoritmo de força bruta para detectar um polígono de auto-interseção

Inicialmente implementei o algoritmo Hoey-Shamos, mas ele é muito complexo para manutenção futura (não tenho nada a dizer sobre isso), e ele não estava reportando corretamente, então um algoritmo de força bruta otimizado é o que eu vou usar.

Minha pergunta é: como posso otimizar esse código para ser utilizável?

Como está, meu código contém um loop aninhado, iterando a mesma lista duas vezes.

EDIT: Transformou linhas em um HashSet e usou dois loops foreach ... raspou cerca de 45 segundos da varredura de 10.000. Ainda não é suficiente.

foreach (Line2D g in lines)
{                   
foreach (Line2D h in lines)
{
    if (g.intersectsLine(h))
    {
        return false;
    }
}                  

 } // end 'lines' for each loop

Se eu forçar o método "intersectsLine ()" a retornar false (para fins de teste), ainda demorará 8 segundos para varrer 10.000 registros (tenho 700.000 registros). Isso é muito longo, então eu preciso otimizar esse pedaço de código.

Eu tentei remover linhas da lista depois que ela foi comparada a todas as outras linhas, no entanto, há um problema de precisão (não sei por que) e o aumento de velocidade é quase imperceptível.

Aqui está o meu método intersectsLine. Eu encontrei uma abordagem alternativaAqui mas parece que seria mais lento com todas as chamadas de método e outros enfeites. Calcular a inclinação não me parece que seria preciso muita computação (corrija-me se estiver errado?)

public bool intersectsLine(Line2D comparedLine)
{

//tweakLine(comparedLine);
if (this.Equals(comparedLine) ||
    P2.Equals(comparedLine.P1) ||
    P1.Equals(comparedLine.P2))
{
    return false;
}

double firstLineSlopeX, firstLineSlopeY, secondLineSlopeX, secondLineSlopeY;

firstLineSlopeX = X2 - X1;
firstLineSlopeY = Y2 - Y1;

secondLineSlopeX = comparedLine.X2 - comparedLine.X1;
secondLineSlopeY = comparedLine.Y2 - comparedLine.Y1;

double s, t;
s = (-firstLineSlopeY * (X1 - comparedLine.X1) + firstLineSlopeX * (Y1 - comparedLine.Y1)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY);
t = (secondLineSlopeX * (Y1 - comparedLine.Y1) - secondLineSlopeY * (X1 - comparedLine.X1)) / (-secondLineSlopeX * firstLineSlopeY + firstLineSlopeX * secondLineSlopeY);

if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
    //console.WriteLine("s = {0}, t = {1}", s, t);
    //console.WriteLine("this: " + this);
    //console.WriteLine("other: " + comparedLine);
    return true;
}

return false; // No collision */

}

EDITAR: O maior gargalo são os grandes polígonos! Excluí polígonos em execução com mais de 100 linhas e executava todos os 700.000 polígonos em 5:10. Qual é o intervalo aceitável! Certamente há uma maneira de ver se vale a pena calcular um polígono antes de executar este código? Eu tenho acesso às propriedades XMin, Xmax, YMin e YMax se isso ajudar?

Fiz outro teste, limitando os polígonos a menos de 1000 linhas cada. Demorou um pouco mais de uma hora.

Eu removi toda a limitação de polígonos, e ela está funcionando há 36 horas agora ... ainda sem resultados.

Algumas ideias que tenho:

-Quando eu gerar minhas linhas hashset, tenha outro hashset / List que tenha candidatos para interseção. Eu só adicionaria linhas a essa lista se houvesse uma chance de interseção. Mas como eliminar / adicionar possibilidades? Se houver apenas três linhas que poderiam se cruzar com outras, eu estaria comparando 4.000 linhas contra 3 em vez de 4. Isso sozinho poderia fazer uma enorme diferença.

-Se o mesmo ponto ocorrer duas vezes, exceto o primeiro e o último ponto, omita a execução do loop for aninhado.

Editar:

Informações sobre os polígonos: 700.000 no total

Existem mais de quatro mil polígonos com 1.000 ou mais pontos

Existem 2 polígonos com 70.000 ou mais pontos

Acho que é possível fazer isso com quinze minutos ou mais com um pouco de criatividade.

questionAnswers(3)

yourAnswerToTheQuestion