none
Problemas de desenhar uma linha... RRS feed

  • Pergunta

  • Olá pessoal,  como estão?

     

    Estou com um problema aqui, e não consigo solucionar, tenho lido alguns ebooks que baixei e procurando muito no site da msdn e nada também.

    O problema é o seguinte:

     

    Tenho uma classe figura que herda da classe Image, crio objetos dessa classe e daí insiro no canvas. Bom faço a movimentação normal com esses objetos.

     

    O problema é quando vou desenhar uma linha. Eu clico numa imagem e daí é selecionada a primeira coordenada da reta, clico depois num outra figura, assim  a reta contém a segunda coordenada, então a reta é desenhada e inserida no canvas.

     

    //pega a posição atual do elemento

    double currentLeft = Convert.ToDouble(moveElemento.GetValue(Canvas.LeftProperty));

    double currentTop = Convert.ToDouble(moveElemento.GetValue(Canvas.TopProperty));

    //calcula a posicao

    double newLeft = currentLeft + pt.X - posicaoClick.X;

    double newTop = currentTop + pt.Y - posicaoClick.Y;

     

    Isso eu faço na movimeentação da figura.

     

    Bom é isso que faço para capturar a posição da figura?

     

    E gostaria que as coordenadas referenciasse as posições das figuras, com isso ao mover uma das figuras a reta é desenhada na coordenada correspondente.

     

    Bom pessoal, me desculpe, mas gostaria de pudesse me ajudar, não estou achando solução.

     

    Obrigado.

     

    Abraços.

    terça-feira, 22 de janeiro de 2008 10:24

Respostas

  • Não faz diferença se um nó é origem ou destino. O que você tem que olhar é quantas retas entram ou saem do nó. A lista de retas guarda todas as retas que usam o nó como origem ou destino. Você deve movimentar todas as retas quando movimenta o nó, tanto a que se origina dele quanto as que se destinam a ele. A rotina de movimentação é a mesma caso o nó seja origem ou destino da reta.

    Bruno
    quarta-feira, 23 de janeiro de 2008 13:48

Todas as Respostas

  • Quando você desenha a reta, desenha ela em relação à posição da figura. Basta então fazer a mesma rotina, reposicionando o ponto inicial ou final da reta quando está movimentando.

    Bruno
    terça-feira, 22 de janeiro de 2008 11:44
  • Bruno,

     

    Obrigado pela ajuda.

    Mas deixa eu explicar melhor...

     

    Tenho uma classe No essa classe Nó deriva da classe Image.

    Tenho uma classe Reta que tem atributo Line, menucontext, color, text, e dois atributos do tipo No.

     

    entao o canvas possui 3 eventos de mover mouse:

    PreviewMouseLeftButtonDown : cria o objeto do tipo no ou line de acordo com o botão clicado. E faz a verificação se o objeto existe, pois joga a figura para uma variavel para depois fazer a movimentação.

     

    PreviewMouseMove: Move o No - image.

     

    PreviewMouseLeftButtonUp: exclui o objeto que está no auxiliar. Serve para o No objeto e para a reta. No caso da reta verifica se a reta pode ser traçada.

     

    Bom, qdo clico o botão de reta entao é ativado uma variavel que denota reta. entao eu seleciono uma imagem dando um clique nela e depois com o mouse solto eu clico em outra imagem. Dai quando solto o botão esquerdo do mouse a figura é desenhada.

     

    Bom nessa hora eu passo os dois nNós para a Reta entao ela pega esses objetos e calcula a posição deles no canvas e entao desenha a reta e adiciona no canvas.

     

    Gostaria que as cooordenadas dessa reta fosse  uma referencia a posições desses dois Nós.

    E quando movimentar uma figura e tiver uma linha saindo dela ee várias outras chegando nela terão que movimentar todas com a figura do movimento.

     

    Por isso eu não sei o que fazer.

    Você poderia me ajudar?

    terça-feira, 22 de janeiro de 2008 16:54
  • Pelo que você está dizendo, você passa a posição dos dois nós para a reta e cria a reta não?
    Então guarde as retas que chegam no nó em uma lista. Quando estiver movendo o nó, faça um foreach na lista, passando a nova coordenada do nó para a reta, numa função MoveReta. Algo mais ou menos assim, no PreviewMouseMove:

    foreach (Reta r in NoAtual.ListaRetas)
       r.Move(No.Coordenadas, NoAtual);

    Esta função Move irá reposicionar o X1,Y1 ou X2,Y2 da reta. Estou passando o NoAtual, assim você sabe se é no início ou final da reta.

    Bruno
    terça-feira, 22 de janeiro de 2008 18:36
  • Bruno mais uma vez obrigado pela ajuda e paciência,

     

    Bom to fazendo assim o programa:

     

     

    public No:Image

    {

    private Point position;

     

    public void setPosition(Point p)

    {

    position = p;

    }

     

    public Point Position

    {

    get{ return this.position;}

    }

    }

     

    Now, class Reta...it has Line object.

     

    public Reta

    {

    private No noOrigin;

    private No noDestiny;

     

    private Canvas canvas;

    private Line reta;

     

    public Reta(No origin, No destiny, Canvas c)

    {

    this.noOrigin = origin;

    this.noDestiny = destiny;

     

    this.canvas = c;

    drawLine();

    }

     

    private void drawLine()

    {

    reta = new Line();

    reta.X1 = noOrigin.Position.X;

    reta.Y1 = moOrigin.Position.Y;

     

    reta.X2 = noDestiny.Position.X;

    reta.Y2 = noDestiny.Position.Y;

     

    canvas.Children.Add(reta);

    }

    }

     

    is it right?

     

    Well, each line can only conect one Image Object, but one Image Object can receive various Line objects.

    As you saw each line object is linked in some particular point of the Image Object. Can be: Center, Top, Left, Right, Bottom.

    Whenever it to move an Image object the line object that arrived and left Image object move too.

     

    How can I implement PreviewMouseLeftButtonDown, PreviewMouseMove, PreviewMouseLeftButtonUp ?

     

    In PreviewMoveLeftButtonDown was implemented it:

     

    private void canvasDesenho_PreviewMouseLeftButtonDown(Object sender, MouseButtonEventArgs e)

    {

    if(e.Source is Canvas)

    {

    posicaoClick = e.GetPosition(canvasDesenho);  //calculating the Image object

     

    No no = new No(); //No of type Image

    canvasDesenho.Children.Add(no); //Canvas = canvasDesenho

    no.SetValue(Canvas.LeftProperty, posicaoClick.X - (noInicio.Source.Width / 2));

    no.SetValue(Canvas.TopProperty, posicaoClick.Y - (noInicio.Source.Height / 2));

    //calculating the new position of the image object

    posicao.X = Convert.ToDouble(noInicio.GetValue(Canvas.LeftProperty));

    posicao.Y = Convert.ToDouble(noInicio.GetValue(Canvas.TopProperty));

    no.setPosicao(posicao);

    no = null;

    }

    else if (e.Source is No)

    {

    if (ePaletas == EnumPaletas.seta) //enum

    {

    ePaletas = EnumPaletas.moving;

    posicaoClick = e.GetPosition(canvasDesenho); //get position of the image object

    moveElemento = (No)e.Source; //store No object on MoveElemento

    ((No)e.Source).Opacity = 0.5;

    canvasDesenho.CaptureMouse();

    e.Handled = true;

    }

    else if (ePaletas == EnumPaletas.linha) //draw line

    {

    if (noOrigin == null && noDestiny == null)

    {

    noOrigin = (No)e.Source;

    noOrigin.Opacity = 0.5;

    }

    else if (noOrigin != null && noDestiny == null)

    {

    noDestiny = (No)e.Source;

    noDestiny.Opacity = 0.5;

    Reta reta = new Reta(noOrigin, noDestiny, canvasDesenho);

    }

    }

    }

     

    Now, PreviewMouseMove event of the Canvas

     

    private void canvasDesenho_PreviewMouseMove(Object sender, System.Windows.Input.MouseEventArgs e)

    {

    if (ePaletas == EnumPaletas.moving && e.LeftButton == MouseButtonState.Pressed)

    {

    Point pt = e.GetPosition(canvasDesenho); //co-ordinated

    //get the position ofthe Image object

    double currentLeft = Canvas.GetLeft(moveElemento);

    double currentTop = Canvas.GetTop(moveElemento);

     

    //calculate a new position of the image object

    double newLeft = currentLeft + pt.X - posicaoClick.X;

    double newTop = currentTop + pt.Y - posicaoClick.Y;

     

    //verify if image object is insede canvas

    if ((newLeft < 0) || (newTop < 0) || (newLeft + moveElemento.ActualWidth > canvasDesenho.ActualWidth) ||

    (newTop + moveElemento.ActualHeight > canvasDesenho.ActualHeight))

    {

    if (newLeft < 0)

    newLeft = 0;

    if (newTop < 0)

    newTop = 0;

    if (newLeft + moveElemento.ActualWidth > canvasDesenho.ActualWidth)

    {

    sizeX += 10.0;

    canvasDesenho.Width = sizeX;

    scrollViewerDesenho.ScrollToRightEnd();

    }

    if (newTop + moveElemento.ActualHeight > canvasDesenho.ActualHeight)

    {

    sizeY += 10.0;

    canvasDesenho.Height = sizeY;

    scrollViewerDesenho.ScrollToBottom();

    }

    }

    //res-position the image object

    moveElemento.SetValue(Canvas.LeftProperty, newLeft);

    moveElemento.SetValue(Canvas.TopProperty, newTop);

     

    //calculating the position

    posicao.X = Canvas.GetLeft(moveElemento);

    posicao.Y = Canvas.GetTop(moveElemento);

     

    moveElemento.setPosicao(posicao);

    posicaoClick = pt;

    e.Handled = true;

    }

    }

     

    Now, Preview Mouse Left Button Up event

     

    private void canvasDesenho_PreviewMouseLeftButtonUp(Object sender, System.Windows.Input.MouseEventArgs e)

    {

    if (ePaletas == EnumPaletas.moving)

    {

    //restore hte values

    moveElemento.Opacity = 1;

    moveElemento.SetValue(Canvas.ZIndexProperty, ++currentZ);

    //calculating the postion

    posicao.X = Convert.ToDouble(moveElemento.GetValue(Canvas.LeftProperty));

    posicao.Y = Convert.ToDouble(moveElemento.GetValue(Canvas.TopProperty));

    moveElemento.setPosicao(posicao);

    moveElemento = null;

    ePaletas = EnumPaletas.seta;

    canvasDesenho.ReleaseMouseCapture();

    }

    else if (ePaletas == EnumPaletas.linha)  //line

    {

    if (noOrigin != null && noDestiny != null)

    {

    //restura os valores

    noOrigin.Opacity = 1;

    noDestiny.Opacity = 1;

    noOrigin.SetValue(Canvas.ZIndexProperty, ++currentZ);

    noDestiny.SetValue(Canvas.ZIndexProperty, ++currentZ);

    noOrigin = null;

    noDestiny = null;

    }

     

    }

     

     

    Legal o jeito que você falou de inserir as retas numa lista.

     

    Bom, mas cada No liga no tem no maximo uma reta entao acho q tenho q declarar uma reta dentro do No class.

    Um No objeto pode ter infinitas retas chegando a ele.

     

    Na classe No a position é a posição do No no canvas, mas estou querendo colocar mais posições como topo, baixo, centro, esquerda, direita. Isso servirá para posicionar o inicio e o fim da reta nos Nós.

     

    Bruno, obrigado mesmo. abraços

     

    terça-feira, 22 de janeiro de 2008 19:42
  • Se no objeto No você pode ter infinitas retas chegando a ele, deve criar uma lista com todas as retas que chegam nele, pois quando mover um nó, deve mover todas as retas, não?

    Bruno
    terça-feira, 22 de janeiro de 2008 20:40
  • Bruno,

     

    Isso mesmo que você disse. Um objeto Nó pode no máximo ter uma reta ligando ao outro objeto Nó. Pode também no objeto Nó chegar várias retas a ele.

     

    Poderia então criar uma lista de retas, daí na classe reta tem dois objetos Nò. Quando mover, percorro toda a lista de retas e o objeto reta que tiver em umas das extremidades o mesmo objeto Nó faço o calculo da posição.

     

    Porém preciso criar um atributo Linha na classe Nó, pois o objeto Nó só pode ter uma reta, nada mais que isso.

     

    O que você acha Bruno?

     

    Muito obrigado pela ajuda.

    quarta-feira, 23 de janeiro de 2008 10:23
  • Afinal, o nó pode ter uma reta ou muitas retas? Faça o seguinte:

    Na classe Nó, crie uma lista de retas, guardando todas as retas que chegam nele. Ao criar uma reta, passe os nós das extremidades.
    Quando você movimenta o nó, faça um foreach na lista de retas:

    foreach (reta in listaretas)
      reta.Move(No);

    Na função Move você reposiciona a reta.

    Bruno
    quarta-feira, 23 de janeiro de 2008 12:30
  • Bruno,

     

    o Nó pode no máximo uma reta. Exemplo: Tenho 3 imagens A, B, C. Faço uma reta ligando AB, BC, CA. Não é permitido criar uma nova ligação envolvendo A, pois A ja tem uma ligação (AB). Veja que A é destino de várias ligações.

     

    Resumindo:

    Um Nó pode ser detino de várias retas, mas um Nó pode ser no MAXIMO UM na origem da reta.

     

    Então poderia fazer do jeito que você disse:

    Cria uma lista de reta na classe Nó, e verificar e o Nó é origem de alguma reta senao a reta é traçada.

     

    Na movimentação faço o membro que você disse:

    percorro toda lista e vou setando as novas posições da reta com relação ao Nó objeto.

     

    certo?

     

    Muito obirgado Bruno.

     

    quarta-feira, 23 de janeiro de 2008 13:35
  • Não faz diferença se um nó é origem ou destino. O que você tem que olhar é quantas retas entram ou saem do nó. A lista de retas guarda todas as retas que usam o nó como origem ou destino. Você deve movimentar todas as retas quando movimenta o nó, tanto a que se origina dele quanto as que se destinam a ele. A rotina de movimentação é a mesma caso o nó seja origem ou destino da reta.

    Bruno
    quarta-feira, 23 de janeiro de 2008 13:48