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
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
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):
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
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
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
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é