Capítulo
4: Sistema de Coordenadas Normalizado e suas Alternativas, Navegação
Estendida com a Window e Clipping (Recorte)

4.1.
Introdução
4.2.
Sistemas de Coordenadas Intermediários e Navegação
Extendida em 2D.
4.3.
Clipping
4.4.
Código-Exemplo
de Clipping
4.1. Introdução
Figura 4.1. Relacionamento
entre Window e Viewport visto até agora.
Figura 4.2. Resultado esperado
na geração da visualização de um objeto geométrico
complexo
Figura 4.3. Duas visões
de uma cena. Em (a) a Window encontra-se distante e em (b) próxima.
Figura 4.4. Navegação
com a Window através de rotação e resultado na Viewport.
4.4.
Código-Exemplo de Clipping
/*
Algoritmo de Cohen-Sutherland adaptado para "C" */
/*
Fonte: Foley & van Dam
Versão em português:
Instituto de Ciências Matemáticas e de Computação
- USP */
typedef enum {LEFT=
Q, RIGHT = 1 , BOTTOM = 2, TOP = 3} aresta;
typedef enum {TRUE
= 1 ,FALSE = 0} boolean;
typedef boolean
outcode;
float xmax, ymax, xmin,
ymin; /* variaveis globais */
boolean Vazio(outcode
codigo[])
/*
retorna TRUE se todos os outcodes em codigo sao FALSE,
e FALSE caso contrario */
{
/*
... procedimento auxiliar */
}
boolean InterseccaoVazia(outcode
codigo0[], outcode codigo1 [])
/*
retorna TRUE se a interseccao logica entre codigo1 e codigo 2 e vazia,
e FALSE c.c. */
{
/* ... procedimento auxiliar */
}
boolean igual(outcode
codigo0[], outcode codigo1[])
/* retorna TRUE se codigo0
e codigo 1 sao iguais, e FALSE c.c. */
{
/*
... procedimento auxiliar */
}
void CalculaOutCode(float
x,float y,outcode codigo[])
/*
calcula outcode para ponto (x,y) */
{
int i;
for (i - LEFT; i <
= TOP; i + + ) codigo[i] = FALSE;
if
y > ymax) codigo[TOP] = TRUE;
else
if (y < ymin) codigo[BOTTOM] = TRUE;
else;
if
(x > xmax) codigo[RIGHT] = TRUE;
else
if (x < xmax) codigo[BOTTOM] = TRUE;
else;
}
void RecorteLinhaCohenSutherland(float
x0,float y0,float x1,float y1,int valor)
/*
algoritmo de recorte de Cohen-Sutherland para linha P0(x0,y0) a P1(x1,y1),
e retangulo de recorte com diagonal de (xmin,ymin) a (xmax,ymax). */
{
boolean aceito, pronto;
outcode outcode0[4],
outcode1 [4], *outcode0ut;
/*
outcodes para P0, P1 e quaisquer outros pontos que estao fora do retangulo
de recorte */
float x, y;
aceito = FALSE;
pronto = FALSE;
CalculaOutCode(x0,y0,outcode0);
CalcuiaOutCode(xl ,y1
,outcode1);
do {
if
(vazio(outcode0) && vazio(outcode1))
{
/* aceitacao trivial e sai */
aceito = TRUE; pronto = TRUE;
}
elseif
(interseccao_vazia(outcode0,outcode1))
/* rejeicao trivial e sai */
pronto = TRUE;
else
{
/* ambos os testes falharam, entao calcula o segmento
de reta a recortar:
a partir de um ponto externo a uma interseccao com a aresta de recorte
*/
/* pelo menos um ponto esta fora do retangulo de
recorte; seleciona-o */
outcode0ut= vazio(outcode0) ? outcode1 : outcode0;
/ * acha agora o ponto de interseccao, usando as
formulas:
y = y0 + inclinacao * (x-x0), x = x0 + ( 1 /inclinacao) * (y-y0) */
if (outcodeOut(TOP))
{ / * divide a linha no topo do retangulo de recorte
*/
x= x0 + (x1-x0) * (ymax-y0)/(y1-y0); y= ymax;
}
else if (outcode0ut[BOTTOM])
{ /* divide a linha na base do retangulo de recorte
*/
x = x0 + (x1-x0) + (ymin-y0)/(y1-y0); y = ymin;
}
else if (outcode0ut[RIGHT])
{ /* divide na aresta direita do retangulo de recorte
*/
y = y0 + (y1 -y0) + (xmax-x0)/(x1-x01; x = xmax;
}
else if (outcode0ut[LEFT])
{ /* divide na aresta esquerda do retangulo
de recorte */
y = y0 + (y 1 -y0) + (xmin-x0)/(x1-x0);
x = xmin;
}
else;
/* agora move o ponto externo para o ponto de interseccao,
para recortar e preparar para o proximo passo */
if (igual(outcode0ut,outcode0))
{
x0 = x;
y0 = y;
CalculaOutCode(x0,y0,outcode0);
}
else {
x1 = x;
y1 = y;
CalculaOutCode(x1,y1,outcode1);
}
} /* fim do else da subdivisao * /
}
while
(pronto);
if (aceito)
/*
AGORA me deixam calcular a intersecção.... */
MeioPontoLinhaReal(x0,y0,x1,y1),valor);
/*
OBS: versao do algoritmo para coordenadas reais */
} /*
fim do algoritmo de recorte e tracado */
/*
Algoritmo de Sutherland-Hodgman para recorte do polígonos */
/*
Fonte: Foley & van Dam
Versão em português:
Instituto de Ciências Matemáticas e de Computação
- USP */
#define MAX 20
typedef struct {float
x,y;} ponto;
typedef ponto vertice;
typedef vertice aresta[2];
typedef vertice VetorVertices[MAX];
typedef enum {TRUE =
1, FALSE = 0} boolean;
void saida(vertice
novoVertice, int *tamSaida, VetorVertices vetorSaida)
/*
acrescenta um novo vertice a vetorSaida, e atualiza tamSaida */
{
/* ... procedimento auxiliar */
}
boolean dentro(vertice
testeVertice, aresta arestaRecorte)
/*
checa se o vertice esta dentro ou fora da aresta de recorte */
{
/*
... procedimento auxiliar */
}
vertice intercepta(vertice
prim, vertice seg, aresta arestaRecorte)
/*
recorta a aresta (prim,seg) do poligono contra arestaRecorte, retorna o
novo ponto */
{
/*
... procedimento auxiliar */
}
void RecortePoligonosSutherlandHodgman(
VetorVertices vetorEntrada, /* vetor de vertices
de entrada */
VetorVertices vetorSaida, /* vetor de
vertices de saida */
int tamEntrada,
/* numero de entradas em vetorEntrada */
int tamSaida,
/* numero de vertices em vetorSaida */
aresta arestaRecorte)
{
vertice
s, p; /* pontos inicial e final da aresta de recorte corrente */
vertice
i; /* ponto de interseccao com uma aresta de recorte */
int j;
/* contador para o loop de vertices */
*tamSaida
= 0;
s = vetorEntrada[tamEntrada];
/ * comeca com o ultimo vertice em vetorEntrada */
for
(j = 1 ;j < = tamEntrada;j + + )
{
p= vetorEntrada[j]; /* agora s e p correspondem aos vertices na Fig. */
if (dentro(s,arestaRecorte))
{ /* casos 1 e 4 */
if (dentro(s,arestaRecorte)) saida(p,tamSaida,vetorSaida);
else {
i = intercepta(s,p,arestaRecorte);
saida(i,tamSaida,vetorSaida);
saida(p,tamSaida,vetorSaida);
}
}
else
{ /* casos 2 e 3 */
if (dentro(s,arestaRecorte))
{
i = intercepta(s,p,arestaRecorte);
saida(i,tamSaida,vetorSaida);
}
}
s = p;
} /* fim do for */
} /*
fim do algoritmo de recorte */
Pseudocódigo para
Algoritmo de Weiler-Atherton, versão de James C. Miller, Bradley
University.
const int MAXVERT
= 500;
const int MAXPOLYV
= 50;
const int MAXH =
10;
struct Point2D
{float x,y;
};
typedef Point2D Vertices[MAXVERT];
enum VerType = {Polygon,
Intersection};
typedef struct ClipListRec
* ClipPtr;
struct ClipListRec
{ int Vindex;
ClipPtr next;
VerType Kind;
float t;
ClipPtr otherList;
}
struct Polygon
{ int nVertex;
int vert[MAXPOLYV];
ClipPtr list;
}
struct GenPolygon
{ Polygon exterior;
int numHoles;
Polygon Holes[MAXH];
}
GenPolygon Sub,Clip;
int entering[MAXVERT],exiting[MAXVERT];
Vertices V;
int numVertex = 0;
// size of the array of verticies
int clipPoly[MAXVERT];
// a clip polygon
int readPoint();
{ cin >> inX;
cin >> inY;
if (numVertex
< MAXVERT)
{ V[numVertex].x
= inX;
V[numVertex].y = inY;
idNo = numVertex;
numVertex++;
}
else
idNo = -1;
return idNo;
}
void readPolygon (GenPolygon
p)
{ cin >> p.exterior.nVertex;
for (i = 0; i
< p.exterior.nVertex; i++)
{ newId = readPoint();
if
(newId < 0)
error
else
{
insertAtRear (p.exterior.list,newId);
p.exterior.vert[i] = newId;
}
}
// now do the
holes basically the same way
. . .
}
// the "main" program
loop would then be (pseudocode)
while (!EMPTY(entering))
{ nextInter = delete
(entering);
SEARCH (SubjectPolygon,nextInter,ptr1);
AddToOutputList
(ptr1->. . .)
StartPoint =
ptr1->. . .
ptr1 = prt1->next;
while (ptr1->.
. . != StartPoint)
{ AddToOutputList
(ptr1->. . .);
if
(ptr1-> . . == INTERSECTION)
ptr1 = prt1->otherList->next;
else
ptr1 = ptr1->next;
}
FixListForOutput();
DrawPolygon();
EmptyOutputList();
}
Links Interessantes:
Apostila
em Português (incompleta)
Poly
clipping
Polygon
clipping
Parametric
line clipping
Code
for various poly and line clipping methods among other things
Frustrum
clipping doc with source code
On-Line
Geometric Modeling Notes - Clipping - uses rigorous linear
algebra
The Cyclops
Project
German-Brazilian Cooperation
Programme on IT
CNPq GMD DLR
|
 |
|