Goの反対側:データ分析による描画

Goは、バックグラウンドタスクに最適なユニバーサルプログラミング言語ですが、受信データに基づいて画像を生成する必要がある場合があります。 Goは、ビジュアルオブジェクトの作成に最適です。 この投稿では、 SVGoパッケージを使用してデータに基づいて画像(特にベクターグラフィックス)を作成する方法の1つについて説明します。



SVGoライブラリ 1つのタスクを実行します。SVGを生成してio.Writerに渡します。 GoのI \ Oパッケージでは、必要なインターフェイス(標準出力、ファイル、ネットワーク接続、Webサーバー)を使用して結果を出力できます。



SVGoの場合、円、長方形、線、多角形、曲線などの高レベルのオブジェクトが最も重要です。 スタイルと属性はセカンダリであり、必要に応じて適用されます。







オブジェクトの読み取り、分析、描画。



この例には、次の手順が含まれます。





XMLからデータを取得し、それらからプリミティブSVGオブジェクトを描画し、それらを標準出力に戻す簡単な例次に示します。

独自のデータについては、必要に応じて構造を記述できることを理解する必要があります。同時に、サードパーティサービスのAPIからデータを取得する場合は、それぞれについてデータ構造を記述する必要があります。



入力例:

<thing top="100" left="100" sep="100"> <item width="50" height="50" name="Little" color="blue">This is small</item> <item width="75" height="100" name="Med" color="green">This is medium</item> <item width="100" height="200" name="Big" color="red">This is large</item> </thing>
      
      







まず、入力データの構造を決定します。 Goで要素と属性の対応を確認できます。 たとえば、 構造「thing」には、インデントを指定するTopおよびLeftパラメーター、要素間の距離を設定するsepパラメーター、およびネストされた要素を含むリストであるItemsパラメーターが含まれます。 また、ネストされた各要素には、 WidthHeightNameColorTextなどのパラメーターセットもあります。

 type Thing struct { Top int `xml:"top,attr"` Left int `xml:"left,attr"` Sep int `xml:"sep,attr"` Item []item `xml:"item"` } type item struct { Width int `xml:"width,attr"` Height int `xml:"height,attr"` Name string `xml:"name,attr"` Color string `xml:"color,attr"` Text string `xml:",chardata"` }
      
      







次に、SVGの出力先(この例では標準出力になります)とキャンバスサイズを指定する必要があります。

 var ( canvas = svg.New(os.Stdout) width = flag.Int("w", 1024, "width") height = flag.Int("h", 768, "height") )
      
      







その後、着信データを読み取るための関数を定義します。

 func dothing(location string) { f, err := os.Open(location) if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) return } defer f.Close() readthing(f) }
      
      







次の重要なステップは、着信データのロードと分析を担当する機能を識別することです。 ここでは、Go標準ライブラリに含まれるXMLパッケージを使用します

 func readthing(r io.Reader) { var t Thing if err := xml.NewDecoder(r).Decode(&t); err != nil { fmt.Fprintf(os.Stderr, "Unable to parse components (%v)\n", err) return } drawthing(t) }
      
      







すべてのデータがロードされると、データを調べてオブジェクトを描画します。 これを行うには、SVGoパッケージの機能を使用します。 この場合、各要素の座標(x、y)を設定し、要素の属性で指定されたサイズと色に対応する円を描き、テキストを追加して垂直間隔を適用します。

  func drawthing(t Thing) { x := t.Left y := t.Top for _, v := range t.Item { style := fmt.Sprintf("font-size:%dpx;fill:%s", v.Width/2, v.Color) canvas.Circle(x, y, v.Height/4, "fill:"+v.Color) canvas.Text(x+t.Sep, y, v.Name+":"+v.Text+"/"+v.Color, style) y += v.Height } }
      
      







次に、データファイルの名前を受け取る例の主な機能について説明します

 func main() { flag.Parse() for _, f := range flag.Args() { canvas.Start(*width, *height) dothing(f) canvas.End() } }
      
      







サンプルを起動する例とその結果:

 $ go run rpd.go thing.xml <?xml version="1.0"?> <!-- Generated by SVGo --> <svg width="1024" height="768" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <circle cx="100" cy="100" r="12" style="fill:blue"/> <text x="200" y="100" style="font-size:25px;fill:blue">Little:This is small/blue</text> <circle cx="100" cy="150" r="25" style="fill:green"/> <text x="200" y="150" style="font-size:37px;fill:green">Med:This is medium/green</text> <circle cx="100" cy="250" r="50" style="fill:red"/> <text x="200" y="250" style="font-size:50px;fill:red">Big:This is large/red</text> </svg>
      
      







完成したSVGは次のようになります。





この例を使用すると、さまざまな視覚化ツールを作成できます。 たとえば、私の仕事では、単純な棒グラフ箇条書き 、さらに複雑な円グラフコンポーネント図の両方を作成できるツールを使用しています。



任意のサービスのAPIからのデータに基づいて画像を作成することもできます。 たとえば、「f50」プログラムは単語を受け取り、それに基づいてFlickr APIから取得した画像のグリッドを生成します。 f50は同じアプローチを使用しますが、データはローカルファイルから取得されませんが、Flickr API HTTPSリクエストが生成されます。

使用例:

 f50 sunset
      
      







Flickr APIは次の応答を返します。

 <?xml version="1.0" encoding="utf-8" ?> <rsp stat="ok"> <photo id="15871035007" ... secret="84d59df678" server="7546" farm="8" title="flickr-gopher" ... /> <photo id="15433662714" ... secret="3b9358c61d" server="7559" farm="8" title="Laurence Maroney 2006..." ... /> ... </rsp>
      
      







SVGを作成するには、id、secret、farm、server、およびtitleパラメーターが必要です。

 // makeURI converts the elements of a photo into a Flickr photo URI func makeURI(p Photo, imsize string) string { im := p.Id + "_" + p.Secret if len(imsize) > 0 { im += "_" + imsize } return fmt.Sprintf(urifmt, p.Farm, p.Server, im) } // imageGrid reads the response from Flickr, and creates a grid of images func imageGrid(f FlickrResp, x, y, cols, gutter int, imgsize string) { if f.Stat != "ok" { fmt.Fprintf(os.Stderr, "Status: %v\n", f.Stat) return } xpos := x for i, p := range f.Photos.Photo { if i%cols == 0 && i > 0 { xpos = x y += (imageHeight + gutter) } canvas.Link(makeURI(p, ""), p.Title) canvas.Image(xpos, y, imageWidth, imageHeight, makeURI(p, "s")) canvas.LinkEnd() xpos += (imageWidth + gutter) } }
      
      









結果のSVGをブラウザーで開くと、画像の上にマウスを移動するとそのタイトルが表示され、クリックすると元の画像に移動します。



All Articles