Detectar o ponto de interseção de 2 linhas
-
24-09-2019 - |
Pergunta
Eu tenho 2 (VisualBasic.PowerPacks) linespapes no meu formulário:
TEXTO ALT http://lh4.ggpht.com/_1tpop7dzy1e/s2cijan7ehi/aaaaaaadaw/qwa0jfhebbm/s800/intersection.png
Quando clico em um deles, um menu de contexto específico é exibido. As linhas podem ser movidas pelo usuário. Um menu de contexto está associado a uma linha. No entanto, se o usuário clicar no ponto de interseção (se houver), precisará exibir um outro menu, que selecione uma das linhas de interseção para executar uma ação.
Agora, me pergunto como detectar que 2 (ou mais) linhas são cruzadas no ponto de clique, porque um outro menu de contexto deve aparecer neste caso.
O que eu tentei fazer:
private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
{
// right click only
if (e.Button == MouseButtons.Right)
{
LineShape target =
(shapeContainer1.GetChildAtPoint(e.Location) as LineShape);
if (target != null)
{
Console.WriteLine(new Point(target.X1, target.Y1));
}
}
}
Suponho que tenho apenas linhas de linhas no contêiner. Isso disse que o ShapeContainer não aumentará um evento de Mousedown se alguma forma de linhas estiver sob o mouse.
Mas esse código me dá apenas a linha Mosttop, mas também quero uma lista de outras pessoas.
Solução 5
/// obtains a list of shapes from a click point
private List<LineShape> GetLinesFromAPoint(Point p)
{
List<LineShape> result = new List<LineShape>();
Point pt = shapeContainer1.PointToScreen(p);
foreach (Shape item in shapeContainer1.Shapes)
{
LineShape line = (item as LineShape);
if (line != null && line.HitTest(pt.X, pt.Y))
{
result.Add(line);
}
}
return result;
}
private void shapeContainer1_MouseDown(object sender, MouseEventArgs e)
{
// right click only
if (e.Button == MouseButtons.Right)
{
List<LineShape> shapesList = GetLinesFromAPoint(e.Location);
Console.WriteLine(DateTime.Now);
Console.WriteLine("At this point {0} there are {1} lines.",
e.Location, shapesList.Count);
}
}
Outras dicas
Na sua rede de coordenadas, você tem duas linhas com y1 = ax + c1
e y2 = bx + c2
. Encontre o ponto de interseção onde x1=x2
e y1=y2
y = ax + c1, y = bx + c2
ax + c1 = bx + c2
x = (c2 - c1)/(a - b)
Em seguida, verifique se o ponto de interseção não está além das fronteiras da linha e calcule a proximidade +- pixels ou dois.
Você precisará apenas calcular a interseção de dois segmentos de linha. Isso é bastante simples.
Um cheio, Algoritmo de trabalho é descrito aqui. Ele funciona fora dos segmentos de linha definidos por dois pontos, por isso deve ser fácil de se adaptar à sua situação.
Serhio, isso é simples Matemáticas...
Trabalhe os pontos de interseção de suas linhas (provavelmente faça isso quando forem adicionados e o resultado da loja), então veja se o mouse está próximo o suficiente para exibir o menu de contexto para que você não precise de cliques perfeitos do Pixel.
Além do algoritmo de interseção da linha (como mostrado por várias pessoas nesta página), você precisa dissociar o menu de contexto das linhas. No código pseudo, você precisará de algo como:
onLine1Click:
if intersection then handle intersection
else handle line1 click
onLine2Click:
if intersection then handle intersection
else handle line2 click
Esse manuseio pode estar mostrando o menu de contexto. Acredito que se/então/então/então for necessário resolver seu problema restante.