Matemática 2D e 3D: como criar 1 recta?

Cambalinho

Power Member
Como criar 1 recta, vector\ponto a ponto, sabendo a origem e destino?
imaginemos que temos:
OX, OY, OZ = 10, 20, 30
DX, DY, DZ = 20, 40 ,100
ao percorrer a recta eu não posso fazer isto num ciclo:
X = X + 1
(os mesmo para as outras coordenas)
porque as distancias entre O e D não são as mesmas.
 
Tens duas opções.

A primeira é definir um número de "steps" (ou etapas) entre o ponto O(x,y,z) e o ponto D(x,y,z). Imagina que queres definir 100 etapas, ou seja, 100 ciclos entre o ponto O e o ponto D, a cada ciclo, o valor de X, Y e Z varia de forma diferente como tu já disseste.

Para calcular esse incremento podes calcular a distância entre o ponto D(x,y,z) e o ponto O(x,y,z) a dividir pelo número de etapas, neste caso 100.

Do tipo:

top6o9J.png


A cada ciclo, X iria aumentar 0.1, Y iria aumentar 0.2 e Z iria aumentar 0.7.

A outra opção é usar a norma euclidiana para calcular o número de etapas automaticamente.

Incremento(x,y,z) = [D(x,y,z) - O(x,y,z)] / norm(D(x,y,z) - O(x,y,z))

Em que norm é a função que devolve a norma euclidiana / distancia euclidiana.

Naturalmente que o valor do Incremento em X, Y e Z convém ser guardado numa variável que suporte casas decimais. O mesmo se aplica ao exemplo anterior.

G9if6lS.png
 
Última edição:
é possível obter números inteiros?
entre 10 e 20(X), o 11 pode(pode) pertencer à recta.
(eu preciso de saber os pontos da recta, para começar a desenhar a recta num determinado ponto... e eu para saber esse ponto vou fazer 1 ciclo e testar esse ponto se está dentro de 1 rectangulo... por isso tenho de testar os pontos da recta, mas que façam parte da recta)
 
O valor do incremento em X, Y e Z terá que ser sempre decimal para não teres problemas em omissões de pontos.

O valor do ponto seguinte é calculado somando o valor do incremento. Por exemplo:

z7OdQxx.png


Este código devolve todos os pontos seguintes ao ponto O, já com o valor arredondado para número inteiro:

10 20 31
10 21 32
10 21 33
11 21 34
11 21 35
11 22 36
11 22 37
11 22 38
11 22 39
11 23 40
11 23 40
12 23 41
12 24 42
12 24 43
12 24 44
12 24 45
12 25 46
12 25 47
13 25 48
13 25 49
13 26 50
13 26 51
13 26 52
13 27 53
13 27 54
14 27 55
14 27 56
14 28 57
14 28 58
14 28 59
14 28 60
14 29 60
14 29 61
15 29 62
15 30 63
15 30 64
15 30 65
15 30 66
15 31 67
15 31 68
16 31 69
16 31 70
16 32 71
16 32 72
16 32 73
16 33 74
16 33 75
17 33 76
17 33 77
17 34 78
17 34 79
17 34 80
17 34 80
17 35 81
17 35 82
18 35 83
18 36 84
18 36 85
18 36 86
18 36 87
18 37 88
18 37 89
19 37 90
19 37 91
19 38 92
19 38 93
19 38 94
19 39 95
19 39 96
20 39 97
20 39 98
20 40 99
20 40 100
 
agora preciso entender algumas funções:
1 - norm(), floor() e round() o que esta função faz?(também preciso usar noutra linguagem)
2 - num2str() é para converter 1 numero em string, certo?

este método funciona em 2D?
 
O norm neste caso calcula a distância entre 2 pontos (distância euclidiana). Funciona para pontos em duas ou três dimensões.

Floor arredonda para o número inteiro mais abaixo.
Round é para arredondar para o número inteiro mais próximo.
num2str() foi apenas para imprimir o valor. É a função que converte números em string no MATLAB.

Sobre os arredondamentos há algo que deves ter em conta.
Utilizar a norma euclidiana para o cálculo das “steps” / etapas pode dar origem a um número de etapas com casas decimais. Por exemplo: a distância entre o ponto O e o ponto D é ~73.4847, o que resulta em 73.4847 etapas. Ou seja, num ciclo com números inteiros, as coordenadas do ponto D (que será o último ponto) vão calhar entre o ciclo número 73 e o ciclo número 74. A minha sugestão é acabar o ciclo antes de passar essa marca, daí ter usado floor no arredondamento das etapas. Ou seja, no limite, o ciclo nunca vai passar o ponto D mas é quase certo que não o inclua. Se usares a opção com etapas fixas (por exemplo 100 etapas entre pontos) este problema não se coloca, no entanto, colocam-se outros problemas.
 
muito obrigado por tudo.
é mais 1 etapa para desenhar o 3D no ecra ;)
só ainda não sei como evitar o sobreposto de planos\linhas.... com o tempo também vou resolver isso.
muito obrigado por tudo
 
@Cambalinho Eu estou aqui a complicar uma coisa simples. O problema dos arredondamentos usando a norma euclidiana que eu descrevi na última mensagem pode ser resolvido muito facilmente: calcular o número de etapas e arredondar para número inteiro. Neste caso aconselho a arredondar para cima, usando a função ceil.

Este código faz aquilo que pretendes. Calcula o numero de etapas de forma automática desde o ponto O ao ponto D, inclusive.

JosVoDw.png
 
tentei fazer como voce fez, mas estou a obter resultados incorrectos:

Código:
Private Function DefPosition3D(Origin As Position3D, Destiny As Position3D) As Position3D
    Dim distance As Position3D
    distance.X = Destiny.X - Origin.X
    distance.Y = Destiny.Y - Origin.Y
    distance.Z = Destiny.Z - Origin.Z
    DefPosition3D = distance
End Function

Private Function InCrement(DefPosition As Position3D, Steps As Position3D) As Position3D
    Dim inc As Position3D
    inc.X = DefPosition.X / Steps.X
    inc.Y = DefPosition.Y / Steps.Y
    inc.Z = DefPosition.Z / Steps.Z
    InCrement = inc
End Function

Private Sub Command1_Click()
    Dim O As Position3D
    Dim D As Position3D
   
    O.X = 10
    O.Y = 20
    O.Z = 30
   
    D.X = 20
    D.Y = 40
    D.Z = 100
   
    Dim Steps As Position3D
    Dim inc As Position3D
    Steps = DefPosition3D(O, D)
    inc = InCrement(Steps, Steps)
    Dim nextpoint As Position3D
    Dim X As Integer
    Dim Y As Integer
    Dim Z As Integer
   
    For X = 0 To Steps.X
        For Y = 0 To Steps.Y
            For Z = 0 To Steps.Z
                nextpoint.X = Round(nextpoint.X + Steps.X)
                nextpoint.Y = Round(nextpoint.Y + Steps.Y)
                nextpoint.Z = Round(nextpoint.Z + Steps.Z)
                Picture1.Print CStr(nextpoint.X), CStr(nextpoint.Y), CStr(nextpoint.Z)
            Next Z
        Next Y
    Next X
End Sub
10 20 70
20 40 140
............
 
Esta linha está bem?

Código:
inc = InCrement(Steps, Steps)

É que segundo a declaração da função, o primeiro argumento devia ser outro.

Código:
Private Function InCrement(DefPosition As Position3D, Steps As Position3D) As Position3D
 
pode não estar porque estou a usar o que sei em VB.. desculpa esses erros... mas não estou a ver outra forma.
tenta me orientar para corrigir estes erros
 
@Cambalinho

Uma imagem a duas dimensões não deveria ter um ponto com coordenadas X, Y e Z, portanto no exemplo a seguir, apenas considero pontos X e Y, para ficar a duas dimensões.

Este código faz aquilo que queres. Vai desde o ponto O(x=10,y=20) até ao ponto D(x=20, y=40).

Criei a estrutura Point2D :)

CGHJhV1.png
 
estou a obter maus resultados.. estou a usar Visual Basic 6:

Código:
Public Function Ceiling(MyNum As Double)
    If Math.Round(MyNum, 0) < MyNum Then
        Ceiling = Math.Round(MyNum + 1, 0)
    Else
        Ceiling = Math.Round(MyNum, 0)
    End If
End Function

Private Sub Command1_Click()
    Dim O As Position3D
    Dim D As Position3D
   
    O.X = 10
    O.Y = 20
    O.Z = 30
   
    D.X = 20
    D.Y = 40
    D.Z = 100
   
    Dim Steps As Double
    Steps = Math.Sqr(Math.Abs(D.X - O.X) ^ 2 + Math.Abs(D.Y - O.Y) ^ 2)
    Steps = Ceiling(Steps)
   
    Dim increment As Position3D
    increment.X = (D.X - O.X) / Steps
    increment.Y = (D.Y - O.Y) / Steps
   
    Dim nextpoint As Position3D
    Dim i As Integer
   
    Dim inter As Position3D
   
    For i = 0 To Steps
        nextpoint.X = nextpoint.X + increment.X
        nextpoint.Y = nextpoint.Y + increment.Y
        'nextpoint.Z = nextpoint.Z + increment.Z
        inter.X = Math.Round(nextpoint.X)
        inter.Y = Math.Round(nextpoint.Y)
        Picture1.Print CStr(inter.X), CStr(inter.Y)   ', CStr(inter.z)
    Next i
End Sub
será que a função Ceiling() está correcta?
 
A três dimensões tens de acrescentar a componente Z no cálculo da norma euclidiana:

Em vez de :
Código:
Steps = Math.Sqr(Math.Abs(D.X - O.X) ^ 2 + Math.Abs(D.Y - O.Y) ^ 2)

Terá de ser:
Código:
Steps = Math.Sqr(Math.Abs(D.X - O.X) ^ 2 + Math.Abs(D.Y - O.Y) ^ 2) + Math.Abs(D.Z - O.Z) ^ 2)

Experimenta isto a ver se dá :) Não vi o resto do código.
 
o seu codigo functiona, mas como não tenho o SQRT... nem sei se é o mesmo que SQR e como não tenho
Ceiling()... pode ser mesmo por isso eu não ter resultados esperados
 
Eu meti o Math.Abs(D.Z - O.Z) ^ 2 depois de fechar o parênteses e devia ser antes. Tem de ficar assim:

Código:
Steps = Math.Sqr(Math.Abs(D.X - O.X) ^ 2 + Math.Abs(D.Y - O.Y) ^ 2 + Math.Abs(D.Z - O.Z) ^ 2)

VB6 suporta raíz quadrada (SQR).
E a função ceiling parece-me OK embora não tenha testado.
 
Back
Topo