Qual é a idéia por trás da definição de retângulos com dois pontos? [fechadas]

14

Não é que isso não faça sentido, mas funciona 99% do tempo.

Geralmente, os retângulos gráficos 2D são inicializados, armazenados e manipulados como um par de pontos. Em nenhuma linguagem particular,

class Rect:
   p1, p2: point

Faz mais sentido definir um retângulo como dois valores xe dois valores y, assim:

class Rect
   xleft, xright: int
   ytop, ybottom: int

Com dois pontos, se em algum lugar no código fonte você quiser usar o valor y do topo, você teria que dizer rect.p1.y (hmmm, pare e pense, é p1 ou p2) mas com os quatro valores como membros de dados simples, é claro e direto: rect.ytop (não é necessário pensar!) O uso de dois pontos significa que, ao lidar com a vertical, você tem que emaranhar a horizontal; existe uma relação estranha entre elementos indepenentes.

Como surgiu essa ideia de dois pontos e por que ela persiste? Tem algum benefício sobre as coordenadas x e y vazias?

NOTA ADICIONADA: Essa questão está no contexto de retângulos alinhados X-Y, como em gerenciadores de janelas e kits de ferramentas GUI, não no contexto de formas arbitrárias no aplicativo de desenho e pintura.

    
por DarenW 30.11.2010 / 21:47
fonte

16 respostas

8

Você já considerou que é menos propenso a erros?

Se você usar (Point1, Point2), é muito claro o que você está especificando. Se você fornecer 2 pontos, então o único erro possível é que o usuário tenha misturado seus x e y ao construir os pontos, pois a ordem dos pontos não importa.

Se você fornecer 4 inteiros, se alguém não estiver prestando atenção, eles podem fornecer (x1, x2, y1, y2) quando você quiser (x1, y1, x2, y2) ou vice-versa. Além disso, algumas APIs como a Rect do WCF definem um retângulo como (x, y, largura, altura), o que poderia causar confusão sobre o que (1, 2, 3, 4) significa. Isso é (x, y, w, h) ou (x1, y1, x2, y2) ou (x1, x2, y1, y2)?

Em suma, (Point1, Point2) parece um pouco mais seguro para mim.

    
por 01.12.2010 / 02:43
fonte
9

Sempre gostei de definir um retângulo como um ponto + largura e altura, em que o ponto é o canto superior esquerdo do retângulo.

class Rect {
  float x, y;
  float width, height;
}

Em seguida, adicione os métodos necessários para buscar as outras métricas. Como a versão Java

    
por 30.11.2010 / 23:56
fonte
7

Na verdade, um retângulo não é definido por dois pontos. Um retângulo só pode ser definido por dois pontos se for paralelo aos eixos.

Existem várias maneiras de representar retângulos que são paralelos aos eixos:

  1. Dois pontos diagonalmente opostos
  2. Um ponto de canto, altura e largura
  3. Ponto central, meia altura e largura (incomum, mas às vezes útil).
  4. Como duas coordenadas X e duas coordenadas Y

Para (1), muitas bibliotecas usam uma convenção para determinar quais dois pontos são usados - topLeft e bottomRight, por exemplo.

A escolha da representação pode ser conduzida pelo propósito original da definição do retângulo, mas imagino que ela seja muitas vezes arbitrária . As representações são equivalentes nas informações que elas carregam. Eles, no entanto, diferem na facilidade com que as propriedades do retângulo podem ser calculadas e a conveniência com que as operações podem ser executadas no retângulo.

Os benefícios da definição (1) em relação aos outros incluem:

  • Consistência da API com outros polígonos, linhas etc.
  • topLeft, bottomRight pode ser passado para qualquer método que aceite pontos
  • Os métodos da classe Point podem ser chamados em topLeft, bottomRight
  • A maioria das propriedades pode ser derivada facilmente, por exemplo. bottomLeft, topRight, largura, altura, centro, comprimento diagonal, etc.
por 01.12.2010 / 00:39
fonte
6

Bem, p1: Point e p2: Point irão ter dois int coordenadas neles, então a sua classe não é igual?

E se você armazenar esses dois pontos como objetos Point de primeira classe, não obterá um pouco mais de utilidade deles? Na maioria dos sistemas de coordenadas gráficas que eu conheço, os pontos são subclassificados dessa maneira para criar uma hierarquia de objetos: point -> circle -> ellipse e assim por diante.

Portanto, se você criar um objeto que não use a classe Point , você se divorciou desse objeto do restante da hierarquia de classes.

    
por 30.11.2010 / 21:52
fonte
5

É por isso que gosto do TRect do Delphi. É definido como um registro variante (estrutura de união em C-speak) que pode ser interpretado como um ponto TopLeft e um BottomRight, ou inteiros Top, Left, Bottom e Right, o que for mais conveniente no momento.

    
por 30.11.2010 / 22:33
fonte
4

Certamente, se você definir seu retângulo como:

class Rect
{
    Point bottomLeft;
    Point topRight;
}

então você sabe imediatamente qual é o ponto.

Melhor ainda seria adicionar propriedades extras que permitissem manipular o retângulo em todas as formas que você precisava para o seu aplicativo. Isso simplesmente atualizaria a estrutura de dados subjacente.

Ao adicionar uma transformação à forma, você pode orientar seu retângulo da maneira que desejar. Você ainda precisa de uma caixa delimitadora alinhada por eixo para verificações rápidas de aceitação / rejeição:)

No entanto, se seu modelo permitir retângulos em qualquer orientação sem aplicar uma transformação, "bottom left" e "top right" não terão significado, o que leva de volta a "p1" e "p2" (ou algo equivalente). p>     

por 01.12.2010 / 00:07
fonte
2

Eu acho que faz mais sentido que um retângulo seja representado por uma extensão xey e um ponto; você poderia até mesmo fazer a localização apontar o centro do retângulo para que ele fosse independente da rotação

mas provavelmente foi mais fácil codificá-lo como dois pontos!

    
por 30.11.2010 / 21:56
fonte
2

Eu não gosto disso porque descartamos um potencial grau de liberdade, que essencialmente permite uma rotação arbitrária. Um retângulo 2D geral tem cinco incógnitas (graus de liberdade). Poderíamos especificá-los como as coordenadas de um ponto, os comprimentos dos dois lados que formam um vértice com este ponto e o ângulo da horizontal da primeira linha (assumindo-se o outro como tendo um ângulo de 90 graus a mais). Um número infinito de outras possibilidades também pode ser usado, mas existem cinco quantidades independentes que devem ser especificadas. Algumas escolhas levarão a álgebra mais fácil do que outras, dependendo do que é feito com elas.

    
por 01.12.2010 / 01:21
fonte
1

Não é exatamente a mesma coisa que 2 pontos? Como isso é estranho ... a maioria das rotinas de desenho requer pontos, não separa os componentes x / y.

    
por 30.11.2010 / 21:54
fonte
1

Definir retângulos como pares de pontos permite reutilizar o ponto como um vértice para outra forma. Apenas um pensamento ...

    
por 30.11.2010 / 22:53
fonte
1

Eu acredito que é principalmente para estabelecer uniformidade entre todas as primitivas de forma.

Claro que você pode definir o retângulo de muitas maneiras diferentes, mas como definir um triângulo, uma estrela ou um círculo de uma maneira que possa usar estruturas de dados semelhantes?

Todos os polígonos podem ser definidos por seus pontos, com uma pequena quantidade de lógica para determinar o que fazer com os pontos.

As bibliotecas gráficas operam principalmente nesses polígonos em termos de vértices e arestas, de modo que os pontos e as linhas entre eles, todos os cálculos funcionam nesses dois recursos, bem isso e facetas, mas isso em si é apenas uma função das arestas.

    
por 30.11.2010 / 22:56
fonte
1

Em duas dimensões, armazenar um retângulo como dois pontos é mais claro do que definir um canto específico e uma largura e altura - considere largura ou altura negativa, ou os cálculos necessários para determinar cada opção do outro.

Realizar rotações em um retângulo definido por pontos também é muito mais simples do que um definido com um ponto mais largura e altura.

Espero que o encapsulamento torne essa diferenciação pouco importante como usuário da classe.

Um retângulo deve ser definido como três pontos a serem bem definidos em 3 dimensões. Não tenho certeza absoluta do requisito para definir um retângulo em 4 ou mais dimensões.

    
por 01.12.2010 / 00:49
fonte
1

É completamente arbitrário. Você precisa de quatro informações para desenhar um retângulo. O (s) projetista (s) da biblioteca decidiu representá-lo com dois pontos (cada um com uma coordenada x-y), mas poderia facilmente tê-lo feito com x / y / w / h ou superior / inferior / esquerda / direita.

Suponho que a verdadeira questão do OP é: por que essa escolha em particular foi feita?

    
por 01.12.2010 / 03:38
fonte
1

A escolha dos parâmetros é importante apenas para os projetistas / codificadores de baixo nível.

Os usuários de alto nível precisam pensar apenas em:

  • IsPointInRect
  • Área
  • Intersecção (ou recorte)
  • HasOverlap (igual a Intersection.Area > 0)
  • União (torna-se uma lista de retângulos)
  • Subtração (uma lista de retângulos que representam o mesmo conjunto de pontos que está no recto A, mas não no recto B)
  • Transformar
    • Deslocamentos em X e Y
    • Rotação (0, 90, 180, 270)
    • Dimensionamento em X e Y (veja nota)
  • Sintaxe simples para propriedades Xmin, Xmax, Ymin, Ymax, Largura, Altura, para que o usuário não precise saber a escolha exata dos parâmetros.

Observação: para minimizar a perda de precisão durante a conversão de escala, às vezes é apropriado implementar uma segunda classe Rect que use coordenadas de ponto flutuante, para que os resultados intermediários possam ser armazenados com precisão em uma sequência de transformações e apenas arredondado para inteiro na última etapa.

    
por 01.12.2010 / 07:35
fonte
0

Como diz @Steven, acho que deveria ser em termos de um vetor de tamanho (x, y) point e a (w, h). Isso porque é fácil cair em uma ambiguidade. Suponha que você tenha o seguinte retângulo preenchido a partir do ponto (0,0).

  012
0 XXX
1 XXX
2 XXX

É evidente que a largura e a altura são (3,3), mas qual é o segundo ponto? É (2,2) ou (3,3)?

Esta ambiguidade pode causar todos os tipos de problemas.

Eu aprendi da maneira mais difícil, anos atrás, que é melhor pensar em coordenadas gráficas como as linhas entre os pixels, não como as linhas em que os pixels estão em . Dessa forma não há ambiguidade.

    
por 30.11.2010 / 22:29
fonte
0
Pa(x,y)*-----------------------------------*Pb(x,y)
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)

Podemos definir tanto Pb & Pc assim:

Pb(Pd(x),Pa(y))

e

Pc(Pa(x),Pd(y))

Portanto, não há necessidade de definir todos os quatro pontos devido à simetria

    
por 01.12.2010 / 01:32
fonte