Olá! Seja bem-vindo!

Anteriormente, vimos como trabalhar com geometria no SQL, para fazermos representações gráficas diretamente do Management Studio, hoje mostrarei como desenhar bandeiras no SQL, para explorarmos um pouco do lado divertido desse assunto!

Raramente algo assim aparecerá em uma prova ou entrevista, no entanto, encorajo você a explora-lo pois o “domínio da periferia eventualmente leva ao domínio da região”, e é o caminho que eu desejo para você que acompanha meu blog.

Como desenhar bandeiras no SQL – Bandeira do Brasil

Como vimos no artigo passado, desenhar formas geométricas no SQL, usando os tipos de dados geométricos, é uma tarefa bastante fácil, bastando informarmos as coordenadas dos objetos e o banco de dados cria formas complexas quase que em um passe de mágica.

Isso torna o desenho da bandeira bastante simples. Uni 3 polígonos (retângulo, losango e círculo) em um só resultset seguindo as proporções da nossa bandeira, as quais podemos obter através desse artigo (https://pt.wikipedia.org/wiki/Bandeira_do_Brasil). Veja só:

-- Bandeira do Brasil
select geometry::Parse('
geometrycollection(
polygon((0 0, 20 0, 20 14, 0 14, 0 0)),
polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3)),
curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))
)') bandeira_brasil

bandeira do brasil no sql cores automaticas

A paleta de cores do SSMS

Embora o desenho da bandeira tenha ficado legalzinho, as cores deixaram um pouco a desejar, então vamos melhorar isso.

Para começar, precisamos conhecer a paleta de cores que o SQL Server Management Studio (SSMS) utiliza para destacar as formas geométricas umas das outras.

Para fazer isso, montei o comando abaixo, que criará uma série de quadradinhos um ao lado do outro.

Como cada quadradinho é uma figura geométrica, o SQL pintará cada um deles com uma cor da paleta, permitindo que a conheçamos. Veja só:

-- Paleta de cores do SQL (poderia ser mais fácil para procurar uma cor, né??)
declare @cores table (id int identity (1,1), poligono geometry)
;with cte_seq as (select 1 as i union all select i + 1 from cte_seq where i < 1000 )
insert into @cores (poligono)
select 'POLYGON (('+x1+' '+y1+', '+x2+' '+y2+', '+x3+' '+y3+', ' +x4+' '+y4+', '+x5+' '+y5+'))'
from (
select
x1 = convert(varchar, row_number() over (partition by y1 order by y1)),
y1 = convert(varchar, y1),
x2 = convert(varchar, row_number() over (partition by y1 order by y1) + 1),
y2 = convert(varchar, y1),
x3 = convert(varchar, row_number() over (partition by y1 order by y1) + 1),
y3 = convert(varchar, y1 + 1),
x4 = convert(varchar, row_number() over (partition by y1 order by y1)),
y4 = convert(varchar, y1 + 1),
x5 = convert(varchar, row_number() over (partition by y1 order by y1)),
y5 = convert(varchar, y1)
from (select ntile(20) over (order by (select 1)) as y1 from cte_seq) y1) as pontos
option (maxrecursion 0)
select row_number() over (order by (select 1)) id, poligono from @cores

paleta de cores ssms

De posse da paleta, podemos escolher algumas cores que representem melhor o nosso verde, amarelo e azul da bandeira.

Como pode ver na paleta acima, nas primeiras 1000 cores eu não encontrei tons iguais aos da nossa bandeira, então selecionei algumas que se aproximassem, por exemplo, as cores ID 30 (verde), ID 33 (amarelo) e ID 87 (azul).  

Se você passar o mouse sobre as caixinhas que desenhamos verá o ID de cada uma das cores, no exemplo abaixo, a cor verde (ID 30):

paleta de cores ssms verde

Gerando polígonos com cores específicas

Agora que escolhemos as cores desejadas, o próximo passo é gerar os 3 polígonos (retângulo, losango e círculo) em suas respectivas cores (ID30, ID33 e ID87).

Como o SQL atribui as cores na ordem que vimos na paleta, e não podemos determinar as cores desejadas para cada polígono, vamos fazer uma “gambiarrinha” para forçar o SQL a escolher a cor certa para cada um dos nossos desenhos.

Funciona assim: Sabendo que o SQL desenhará em verde o trigésimo polígono, desenharemos 29 quadrados antes do retângulo da nossa bandeira… Sabendo que a cor 33 será o amarelo, desenharemos 32 polígonos antes do nosso losango, e assim por diante.

Para atingir esse objetivo, criei uma figura chamada “quadrado fantasma” na variável @f. Trata-se de um quadrado tão pequeno, que será desenhado, mas não aparecerá a olho nu no desenho que faremos.

Desenharei 29 desses antes de criar o retângulo da bandeira. Depois, desenharei mais 2 “fantasmas” antes do losango. Por fim, mais 53 “fantasmas” antes do círculo a ser pintado de azul (cor 87). Veja o exemplo:

-- Formas geométricas: Retângulo, losango e Círculo:
declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
-- Quadrado "fantasma"...
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

-- Retângulo em VERDE (cor 30):
select top 29 @f from sys.sysmessages -- 29 desehos do quadrado invisível:
union all select @q -- Desenho do Retângulo (número 30!)

-- Losango amarelo (cor 33)
select top 32 @f from sys.sysmessages -- 32 desenhos do quadrado invisível
union all select @l -- Desenho do Losango (número 33!)

-- Círculo Azul (cor 87):
select top 86 @f from sys.sysmessages
union all select @c
go

poligonos individuais cores bandeira brasil

De posse dos polígonos nas cores que escolhemos, o próximo passo, em princípio, seria junta-los em um só desenho, porém se fizermos isso diretamente você perceberá que as cores ficam diferentes do que vimos acima, veja só:

declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

select top 29 @f from sys.sysmessages
union all
select @q -- 29 + 1 = 30 (verde)
union all
select top 2 @f from sys.sysmessages
union all
select @l -- 30 + 2 + 1 = 33 (amarelo)
union all
select top 53 @f from sys.sysmessages
union all
select @c -- 33 + 53 + 1 = 87
go

bandeira do brasil em cores 1

Perceba que o verde está ok, mas o amarelo e o azul tornaram-se mais escuros… Isso ocorre porque as cores da paleta são ligeiramente transparentes, gerando uma “mistura” quando sobrepomos os polígonos. Mas há solução…

Reduzindo polígonos para ajustar as cores

Para resolver esse último problema (sobreposição das cores), vamos reduzir os polígonos da seguinte forma:

– Removeremos o losango de dentro do retângulo

– Removeremos o círculo de dentro do losango

Você pode achar que isso seria complicado, mas definitivamente não é! Com a função STDifference o SQL faz isso para nós de barbada! Veja só:

-- Retângulo, losango e circulo
declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

-- Salva poligonos originais:
declare @poligonos_originais table (id int identity(1, 1) primary key, poligono geometry)
insert into @poligonos_originais (poligono) values (@q), (@l), (@c)

-- Impedindo interseções para não misturar cores
declare @poligonos_reduzidos table (id int identity(1, 1) primary key, poligono geometry)
set @q = @q.STDifference(@l) -- removendo o losango do retângulo
set @l = @l.STDifference(@c) -- removendo o círculo do losango
insert into @poligonos_reduzidos (poligono) values (@q), (@l), (@c)

-- Comparação de desenho: Polígonos originais vs polígonos reduzidos
--select * from @poligonos_originais
--select * from @poligonos_reduzidos

-- Desenhando a bandeira:
declare @bandeira table (id int identity(1, 1) primary key, poligono geometry)
-- Retângulo verde
insert into @bandeira (poligono) select top 29 @f from sys.sysmessages
insert into @bandeira (poligono) values (@q)
-- Losango Amarelo:
insert into @bandeira (poligono) select top 2 @f from sys.sysmessages
insert into @bandeira (poligono) values (@l)
-- Círculo Azul
insert into @bandeira (poligono) select top 53 @f from sys.sysmessages
insert into @bandeira (poligono) values (@c)

select poligono from @bandeira order by id
go

bandeira brasil cores 2 stdifference

Script completo da aula

Baixe o script completo da aula de hoje aqui:

[sociallocker id=5114]


---------------------------------------------------
-- Geometry: Curiosidades - Desenhando bandeiras...
---------------------------------------------------
-- Bandeira do Brasil
select geometry::Parse('
geometrycollection(
polygon((0 0, 20 0, 20 14, 0 14, 0 0)),
polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3)),
curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))
)') bandeira_brasil

/* Referências de medida da bandeira:
https://pt.wikipedia.org/wiki/Bandeira_do_Brasil
https://upload.wikimedia.org/wikipedia/commons/b/be/Flag_of_Brazil_%28dimensions%29.svg
*/

---------------------------------------------------
-- Paleta de cores do SQL
---------------------------------------------------
-- Paleta de cores do SQL (poderia ser mais fácil para procurar uma cor, né??)
declare @cores table (id int identity (1,1), poligono geometry)
;with cte_seq as (select 1 as i union all select i + 1 from cte_seq where i < 1000 )
insert into @cores (poligono)
select 'POLYGON (('+x1+' '+y1+', '+x2+' '+y2+', '+x3+' '+y3+', ' +x4+' '+y4+', '+x5+' '+y5+'))'
from (
select
x1 = convert(varchar, row_number() over (partition by y1 order by y1)),
y1 = convert(varchar, y1),
x2 = convert(varchar, row_number() over (partition by y1 order by y1) + 1),
y2 = convert(varchar, y1),
x3 = convert(varchar, row_number() over (partition by y1 order by y1) + 1),
y3 = convert(varchar, y1 + 1),
x4 = convert(varchar, row_number() over (partition by y1 order by y1)),
y4 = convert(varchar, y1 + 1),
x5 = convert(varchar, row_number() over (partition by y1 order by y1)),
y5 = convert(varchar, y1)
from (select ntile(20) over (order by (select 1)) as y1 from cte_seq) y1) as pontos
option (maxrecursion 0)
select row_number() over (order by (select 1)) id, poligono from @cores

---------------------------------------------------
-- Bandeira com as cores - formas individuais
---------------------------------------------------
-- Formas geométricas: Retângulo, losango e Círculo:
declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
-- Quadrado "fantasma"...
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

-- Retângulo em VERDE (cor 30):
select top 29 @f from sys.sysmessages -- 29 desehos do quadrado invisível:
union all select @q -- Desenho do Retângulo (número 30!)

-- Losango amarelo (cor 33)
select top 32 @f from sys.sysmessages -- 32 desenhos do quadrado invisível
union all select @l -- Desenho do Losango (número 33!)

-- Círculo Azul (cor 87):
select top 86 @f from sys.sysmessages
union all select @c
go

---------------------------------------------------
-- Bandeira do Brasil - Juntando as formas:
---------------------------------------------------
declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

select top 29 @f from sys.sysmessages
union all
select @q -- 29 + 1 = 30 (verde)
union all
select top 2 @f from sys.sysmessages
union all
select @l -- 30 + 2 + 1 = 33 (amarelo)
union all
select top 53 @f from sys.sysmessages
union all
select @c -- 33 + 53 + 1 = 87
go

---------------------------------------------------
-- Bandeira do Brasil - Juntando formas sem mistura de cores
---------------------------------------------------
-- Retângulo, losango e círculo
declare @q geometry = 'polygon((0 0, 20 0, 20 14, 0 14, 0 0))'
declare @l geometry = 'polygon((10 12.3, 18.3 7, 10 1.7, 1.7 7, 10 12.3))'
declare @c geometry = 'curvepolygon(circularstring(6.5 7, 10 10.5, 13.5 7, 10 3.5, 6.5 7))'
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'

-- Salva polígonos originais:
declare @poligonos_originais table (id int identity(1, 1) primary key, poligono geometry)
insert into @poligonos_originais (poligono) values (@q), (@l), (@c)

-- Impedindo interseções para não misturar cores
declare @poligonos_reduzidos table (id int identity(1, 1) primary key, poligono geometry)
set @q = @q.STDifference(@l) -- removendo o losango do retângulo
set @l = @l.STDifference(@c) -- removendo o círculo do losango
insert into @poligonos_reduzidos (poligono) values (@q), (@l), (@c)

-- Comparação de desenho: Polígonos originais vs polígonos reduzidos
--select * from @poligonos_originais
--select * from @poligonos_reduzidos

-- Desenhando a bandeira:
declare @bandeira table (id int identity(1, 1) primary key, poligono geometry)
-- Retângulo verde
insert into @bandeira (poligono) select top 29 @f from sys.sysmessages
insert into @bandeira (poligono) values (@q)
-- Losango Amarelo:
insert into @bandeira (poligono) select top 2 @f from sys.sysmessages
insert into @bandeira (poligono) values (@l)
-- Círculo Azul
insert into @bandeira (poligono) select top 53 @f from sys.sysmessages
insert into @bandeira (poligono) values (@c)

select poligono from @bandeira order by id
go

---------------------------------------------------
-- Bandeira do Japão
---------------------------------------------------
declare @f geometry = 'polygon((0 0, 0.00000001 0, 0.00000001 0.00000001, 0 0.00000001, 0 0))'
select top 295 @f from sys.messages
union all
select geometry::Parse('linestring(0 0, 3 0, 3 2, 0 2, 0 0)')
union all
select geometry::Parse('curvepolygon(circularstring(1.5 1.6, 2.1 1, 1.5 0.4, 0.9 1, 1.5 1.6))')

[/sociallocker]

Conclusão

É sempre bacana quando podemos nos divertir com coisas de trabalho, por isso gostei de mostrar a você como desenhar bandeiras no SQL Server.

Fora esse fato, no caso de formas geométricas, eu, particularmente, acabei me sentindo com maior potencial para desenhar coisas… pois a “mão livre” mal e porcamente sai um boneco de pauzinho kkkkk.

Não sei você, mas eu sou terrível escrevendo e desenhando…

Uma vez li em um livro que a curiosidade é o catalizador da maestria, por isso espero que você também tenha gostado do artigo.

Abraço do seu amigo Josué

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *