메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

SVG 히스토그램

한빛미디어

|

2002-03-13

|

by HANBIT

10,069

저자: 『SVG Essentials』의 저자 데이비드 에이젠버그, 역 이호재

SVG는 확대 축소 가능한 벡터 그래픽(Scalable vector graphics)을 표현하기 위해서 만들어진 XML markup language입니다.
SVG Essentials


SVG가 무엇인지 간략하게 알고싶다면, XML.com의 "확대 축소 가능한 벡터 그래픽 소개"라는 기사를 참조하기 바랍니다. 그 기사에서 예제로 쓰인 카메라 상점을 위한 광고는 손으로 그린 것입니다. 그렇지만 이번 기사에서는 기존 데이터로부터 그래픽을 생성할 것입니다. 특히, 한 디렉토리와 그 서브디렉토리에 있는 파일 크기의 분포 그래프를 그리기 위해 펄 프로그램을 작성할 것입니다.

데이터 가져오기

그래프를 만들기 전에, 데이터부터 수집해야 합니다. 디렉토리를 찾기 위해 File::Find라는 모듈을 사용할 것입니다. 이 프로그램은 다음과 같은 변수 정의에서 시작합니다.

use warnings;
use strict;

use File::Find;

my @file_sizes;
   # array of file sizes
my $total_files;
   # number of files in directory
   # and its subdirectories
my $max_file_size; 
   # maximum file size
그리고 나서 분석할 디렉토리 이름이 올바르게 주어졌는지 검사합니다.

if (scalar @ARGV != 1)
{
    print "Create SVG diagram showing file size ",
        " distribution for a directory\n";
    print "Usage: $0 directory\n";
    exit(0);
}
다음으로 프로그램은 카운터 변수를 초기화하고 디렉토리를 검색합니다.

$total_files = 0;
$max_file_size = 0;
find(\&accumulate, $ARGV[0]);
아래에는 데이터를 수집하는 accumulate라는 함수가 있습니다. 이 함수는 파일의 총 개수와 가장 큰 파일의 크기를 기록하고, 모든 파일 크기는 file_size라는 배열에 저장합니다.

sub accumulate
{
   my @info;

   if (-f $_)
   {
      @info = stat($_);
      push @file_sizes, $info[7];
      if ($info[7] > $max_file_size)
      {
         $max_file_size = $info[7];
      }
      $total_files++;
   }
}
그래픽 만들기

이제는 데이터를 사용할 수 있기 때문에 그래픽을 만들 수 있습니다. x축에 파일 크기를 나타내고 y축에 파일의 개수를 나타낼 수 있지만, 이는 평범하고 지루할 수 있기 때문에, 100개의 섹션으로 나누어진 수평 막대 그래프(bar graph)를 만들 것입니다. 즉, 각 섹션은 파일 사이즈의 1 퍼센트를 표현하고 있는 것입니다. 파일의 개수를 표현하기 위해 해당 영역의 바 크기 대신 해당 섹션의 색을 이용해 표현해 보겠습니다. 색이 진하면 진할수록 그 영역에는 더 많은 파일이 있다는 것입니다. 아래에 이와 같은 형태의 그래프 예가 있습니다. (이 이미지는 이 페이지에 맞게 일부분을 편집하였음)


히스토그램 그래프

그래픽을 만들려면 아래와 같은 표준 SVG 헤더로 시작해야 합니다.

print <<"SVG_HEAD";


그리고 나서 그림의 치수를 결정합니다. 작업을 편하게 하기 위해 ViewBox를 설정하였는데, 이는 SVG 좌표계의 한 단위가 컴퓨터의 한 픽셀과 동일하게 해주는 역할을 합니다. preserveAspectRatio 속성은 그래프가 항상 보이는 영역(viewing area)의 왼쪽 윗부분에 나타나게 하기 위해 설정되었습니다.


주요한 항목(root element)은 제목(title)과 설명(description) 다음에 나옵니다.

    File sizes for $ARGV[0]
    
        Distribution of file sizes
        of $ARGV[0] and its  subdirectories
    
이제 우리는 나중에 분할할 빈 막대를 정의할 것입니다. 그리고 파일 크기 영역의 매 10퍼센트마다 회색 구분선을 표시하기 위해 회색 바를 정의할 것입니다. 작업을 편하게 하기 위해 바의 길이는 600 유닛으로 높이는 20유닛으로 하겠습니다. 빈 막대는 600 * 200 영역에서 0.5 유닛의 outset을 가지고 있으며, 이는 한 유닛으로 선을 그을 때(stroke) 그 외곽선이 데이터를 표시하는 영역과 겹치지 않게 하기 위해서입니다. 마찬가지로 회색 구분 선도 선긋기 폭을 0.5 유닛으로 설정합니다.



   



   


SVG_HEAD
이제는 데이터에 종속적인 그래픽 부분을 그릴 준비가 되었습니다. 이를 위해 아래와 같은 몇 가지 변수가 필요합니다.

my $size;       # 각 파일의 크기
my $i;          # 여러군대의 반복문에서 쓰이는 카운터
my $x;          # 크기 영역의 x 오프셋
my $pct_count;  # 영역에 있는 파일의 %
my $hue;        # 영역의 파란색 정도(파일 퍼센트)
                # 100과 동일
my @slots;      # 각 영역에 있는 파일의 개수
첫번째로 해야할 일은 모든 파일 크기를 조사한 뒤에 파일 영역의 1 퍼센트 영역에 그것들을 분배하는 일입니다. 여기서 100% 영역에 있는 값을 99%영역으로 집어 넣었는데, 이는 0부터 100까지 101개의 영역이 있기 때문입니다.

foreach $size (@file_sizes)
{
   $pct_count = int(100 * $size/$max_file_size);
   if ($pct_count == 100)
   {
      $pct_count = 99;
   }        
   $slots[$pct_count]++;
}
그리고 나서 원점에서 그래프를 옮길 것입니다. 이는 다음과 같은 펄 문장으로 할 수 있습니다.

print qq!\n!;
다음 과정은 디렉토리 이름과 그 디렉토리에 있는 전체 파일의 개수를 표시하는 것입니다. 아래에 이를 표현하는 SVG 코드가 있습니다.

   
   directory ($total_files files)
   
위와 같은 SVG 코드를 생성하기 위해서는 다음과 같은 펄 소스코드가 필요합니다.

print qq!\n!;
print qq!\t\n!;
print qq!\t\t$ARGV[0] ($total_files files)\n!;
print qq!\t\n!;
이제 모든 슬롯을 돌면서 해당 슬롯에 파일이 있다면 적당한 파란 사각형으로 색을 입힐 것입니다. 이를 위해 우리는 파란색을 100퍼센트로 설정하고 파일의 수에 반비례하여 채도를 떨어뜨릴 것입니다. 빨간색과 녹색의 수치를 결정할 때 100이 아닌 95에서부터 빼서 계산했는데 이는 작은 수의 파일이 있는 영역의 색이 아무 파일도 없는 흰색과 구분될 수 있도록 하기 위해서입니다.

예를 들어 15퍼센트의 파일크기 영역에 전체 파일 개수의 20퍼센트가 있다면, 아래와 같은 SVG를 생성하길 원할 것입니다.


아래에 모든 영역의 사각형을 생성하기 위한 펄 코드가 있습니다.

for ($i=0; $i < 100; $i++)
{
   next if (!$slots[$i]);
   $hue =
      95 - int(100 * $slots[$i]/$total_files);
   if ($hue < 0 )
   {
      $hue = 0;
   }
   $x = $i * 6;

   # display the rectangle  
   print qq!\t\n!;
}
이제 우리는 영역을 둘러싸고 있는 막대와 구분자를 그릴 것입니다.

print qq!\t\n!;
print qq!\t\n!;
마지막으로 우리는 킬로바이트에서 파일 크기와 함께 바에 레이블을 달아야 합니다. 우리는 오른쪽, 가운데, 맨 끝만 레이블을 달 것입니다.

print qq!\t\n!;

print qq!\t\t!;
print "0";
print qq!\n!;

print qq!\t\t!;
print int($max_file_size/2048), "k";
print qq!\n!;

print qq!\t\t!;
print int($max_file_size/1024), "k";
print qq!\n!;

print qq!\t\n!;
다음 펄 코드는 SVG 요소를 닫습니다.

print qq!\n!;
print qq!\n!;
아래의 그래프는 이 프로그램을 /usr/include 디렉토리에 적용시켰을 때의 결과입니다.


히스토그램 그래프

그래픽에 숫자 첨가하기

이 시점에서 여러분은 다음과 같이 생각할 수 있습니다. "그래서 어쨌다는 거죠? 나는 펄에 있는 많은 도구을 이용해 JPEG나 PNG 형식의 비슷한 그래픽을 만들 수 있습니다. SVG가 뭐가 좋은지 모르겠네요"

물론 SVG 그래픽이 파일 분포를 잘 나타내 주기는 하지만, 원하는 만큼 많은 정보를 주지 못할 수 있습니다. 15퍼센트와 20퍼센트의 파일 개수를 나타내는 색을 쉽게 구분하지 못할 수도 있지요. 보통 히스토그램에서는 파일 개수 정보를 y축에서 얻을 수 있습니다. 그래서 SVG 그래픽의 각 영역에 파일의 개수를 쓰겠습니다. 만약 숫자가 읽기 어려울 정도로 작기 때문에 이렇게 하는데 반대 한다면 잠시만 기다려주세요.

이렇게 숫자를 넣는 코드를 작성하기 위해 몇 가지 결정을 해야 합니다. 첫째, 사각형의 색이 너무 진하다면 숫자를 명확하게 보기 위해 검은색 숫자대신 하얀색 숫자를 사용해야 합니다. 둘째, 해당 영역에 10개 미만의 파일이 있다면 숫자를 가운데 정렬해야 합니다. 10개 이상이라면 textLength 속성을 이용하여 모든 숫자를 5 유닛 안에 집어 넣어야 합니다. 또 lengthAdjust 속성이 spacingAndGlyphs 값을 갖도록 설정하는데, 이는 SVG가 숫자를 주어진 textLength에 맞도록 하기위해 문자와 문자 사이의 공간을 모두 줄일 것이라는 것을 의미합니다.

다음과 같은 두 개의 영역을 갖고 있는 SVG 코드가 있습니다. 하나는 437개의 파일을 가지고 있고 다른 하나는 5개의 파일을 가지고 있습니다.



   437




    5

이러한 SVG 코드를 만들기 위한 펄 코드는 다음과 같습니다. 이는 for 루프에 들어갈 것이고 결과 그래프는 다음과 같습니다.

if ($slots[$i] < 10)
{
   print
   qq!\t$slots[$i]\n\n!;
}
else
{
   print
   qq!\t$slots[$i]\n\n!;
}


각 섹션에 파일의 개수가 있는 히스토그램

보다시피 숫자를 읽기에는 정말로 너무 작습니다. (계속해서 읽으려 하다가 아마도 눈이 빠질지도 모릅니다.) 만약 우리가 여기서 PNG나 JPEG 그래픽을 생성했다면, 우리는 쓸모없는 그래프를 만든 것입니다. 왜냐하면 큰 이미지를 보기 위해 확대를 하면 아래와 같이 뭉개진 그래프만을 볼 수 있기 때문입니다.


PNG와 JPG에서 확대했을 때의 모습

어쨌든간에 SVG는 각 픽셀이 아닌 벡터(선)를 이용해 확대 축소 가능한 그래픽을 생성합니다. 이는 SVG 파일을 볼 수 있는 프로그램에서 이 파일을 읽은 후 확대해서 숫자도 명확하게 읽을 수 있다는 것을 의미합니다. 이러한 기술은 곧바로 지도 데이터에 응용할 수 있습니다. ㅡ 한 도시의 영역 정보를 담고 있는 지도를 다운로드할 수 있고, 상세한 정보를 위해 서버에 재접속할 필요 없이 기존 지도를 확대할 수 있기 때문.


SVG에서 확대했을 때의 모습

sizegraph.txt란 파일은 전체 프로그램을 보여줍니다.

지금까지 파일 정보를 표현하기 위해 펄 언어와 약간의 창의력, 그리고 벡터 그래픽의 확대 축소능력(scalability)을 사용하였습니다.

더 읽을 거리

물론 SVG의 저작권은 월드 와이드 웹(WWW) 콘소시엄 SVG 페이지에 있습니다. SVG에 관한 더 자세한 정보는 필자가 쓴 『SVG Essentials』를 읽어보시기 바랍니다.

SVG를 볼 수 있는 프로그램이 필요하다면, 어도비사로부터 플러그인을 얻을 수 있습니다. 또 뷰어 프로그램과 SVG 툴은 Apache Batik 프로젝트에서도 얻을 수 있습니다.

만약 펄로 SVG를 만드는 데 있어 다른 방법을 찾고 있다면, RO IT 시스템 사이트에서 그러한 목적에 맞는 모듈을 찾을 수 있을 것입니다. 이 사이트에는 또한 SVG의 인터랙티브한 면을 잘 보여주는 재미있는 예제가 많이 있습니다.
TAG :
댓글 입력
자료실