返回列表 发帖

[原创代码] Perl重绘inkscape生成的矢量图(.svg)

没错,跳票已久的 “然而并没有什么卵用” 系列 (先自嘲一番,即使舆论出了偏差,也有心理准备)

首发 Perl+OpenGL 重绘inkscape生成的svg矢量图

当前主要是绘制路径,细节有待完善。multi.svg 由开源软件 inkscape 绘制并导出,你可以拖入浏览器中查看
=info
    Author: 523066680
      Date: 2016-11
=cut
use IO::Handle;
use OpenGL qw/ :all /;
use OpenGL::Config;
use Time::HiRes 'sleep';
use feature 'state';
STDOUT->autoflush(1);
open READ, "<:raw", "multi.svg";
my @all;
my $tl;
for my $line (<READ>)
{
    if ( $line=~/\s+d="(.*)"/ )
    {
        @all = split(" ",  $1 );
    }
}
my @coords;
for my $e (@all)
{
    if ( $e =~/[a-zA-Z]/ )
    {
        $head = $e;
        next;
    }
    push @coords,
        {
            'head' => $head,
            'data' => [ split(",", $e) ],
        };
}
#相对坐标 叠加为绝对坐标
my ($ox, $oy);
for (my $i = 0; $i <= $#coords; $i++)
{
    if ($coords[$i]->{head} eq 'c')
    {
        grep
        {
            $coords[ $i+$_ ]->{'data'}[0] += $ox;
            $coords[ $i+$_ ]->{'data'}[1] += $oy;
        } (0..2) ;
        $i += 2;
    }
    else
    {
   
    }
    #ox oy 始终是最后一点的坐标值
    ($ox, $oy) = ($coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1]) ;
}
my ($xmin, $xmax, $ymin, $ymax) = (10000.0, -10000.0, 10000.0, -10000.0);
for my $e (@coords)
{
    printf("%.2f, %.2f\n", $e->{'data'}[0], $e->{'data'}[1]);
    $xmin = $e->{'data'}[0] if ($e->{'data'}[0] < $xmin);
    $xmax = $e->{'data'}[0] if ($e->{'data'}[0] > $xmax);
    $ymin = $e->{'data'}[1] if ($e->{'data'}[1] < $ymin);
    $ymax = $e->{'data'}[1] if ($e->{'data'}[1] > $ymax);
}
printf("%f %f %f %f\n", $xmin, $xmax, $ymin, $ymax);
&Main();
sub display
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
    glPushMatrix();
    my $array;
    my @points;
    for (my $i = 0; $i <= $#coords; $i++)
    {
        if ($coords[$i]->{head} =~/C/i)
        {
            glColor4f(0.0,0.5,0.0,1.0);
            $array = OpenGL::Array->new( 3*4, GL_FLOAT);
            @points = (
                        $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0 ,
                        $coords[$i+0]->{'data'}[0], $coords[$i+0]->{'data'}[1], 0.0 ,
                        $coords[$i+1]->{'data'}[0], $coords[$i+1]->{'data'}[1], 0.0 ,
                        $coords[$i+2]->{'data'}[0], $coords[$i+2]->{'data'}[1], 0.0 ,
                        );
            $array->assign(0, @points);
            glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, $array->ptr);
            glMapGrid1f(20, 0.0, 1.0);
            glEvalMesh1(GL_LINE, 0, 20);
            $i+=2;
        }
        elsif ($coords[$i]->{head} =~/Q/i)
        {
            glColor4f(0.0,0.5,0.0,1.0);
            $array = OpenGL::Array->new( 3*3, GL_FLOAT);
            @points = ( $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0,
                        $coords[$i+0]->{'data'}[0], $coords[$i+0]->{'data'}[1], 0.0 ,
                        $coords[$i+1]->{'data'}[0], $coords[$i+1]->{'data'}[1], 0.0 ,
                        );
            $array->assign(0, @points);
            glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 3, $array->ptr);
            glMapGrid1f(20, 0.0, 1.0);
            glEvalMesh1(GL_LINE, 0, 20);
            $i += 1;
        }
        elsif ($coords[$i]->{head} =~/L/i)
        {
            glBegin(GL_LINES);
                glVertex3f(  $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0 );
                glVertex3f(  $coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1], 0.0 );
            glEnd();
        }
        elsif ($coords[$i]->{head} =~/M/i)
        {
            glBegin(GL_POINTS);
                glColor3f(1.0, 1.0, 1.0);
                glVertex3f(  $coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1], 0.0 );
            glEnd();
        }
    }
    glPopMatrix();
    glutSwapBuffers();
}
sub init
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glPointSize(2.0);
    glLineWidth(2.0);
    glEnable(GL_BLEND);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_MAP1_VERTEX_3);
}
sub idle
{
    sleep 0.05;
    glutPostRedisplay();
}
sub Reshape
{
    my $half = 1000;
    glViewport(0, 0, 500.0, 500.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    #glOrtho(-$half, $half, -$half, $half, 0.0, 200.0);
    glOrtho($xmin, $xmax, $ymin, $ymax, 0.0, 200.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0,0.0,100.0,0.0,0.0,0.0, 0.0,1.0,100.0);
}
sub hitkey
{
    my $keychar = lc(chr(shift));
    if ($keychar eq 'q')
    {
        glutDestroyWindow($WinID);
    }
}
sub Main
{
    glutInit();
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(1,1);
    our $WinID = glutCreateWindow("title");
    &init();
    glutDisplayFunc(\&display);
    glutReshapeFunc(\&Reshape);
    glutKeyboardFunc(\&hitkey);
    glutIdleFunc(\&idle);
    glutMainLoop();
}
__END__
要使glMap1f_c 正常工作,需要借用OpenGL::Array 建立一个
仿C的指针
    my $array = OpenGL::Array->new( 3*4, GL_FLOAT);
    $array->assign(0, @points);
    glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, $array->ptr);
    glEnable(GL_MAP1_VERTEX_3);COPY
IE浏览  VS 重绘
1

评分人数

[url=][/url]

本帖最后由 happy886rr 于 2016-11-8 22:14 编辑

图形设计的非常有创意,兼具美学性、艺术性、极坐标性。放大400倍中间居然是个11角星。
花非花、雾非雾。
读君的代码就像在读诗。

TOP

本帖最后由 523066680 于 2016-11-9 11:55 编辑

回复 2# happy886rr


    (莫夸,要飞起来了……
    (其实我的代码自带混淆,有待改善
[url=][/url]

TOP

本帖最后由 523066680 于 2016-11-9 12:04 编辑

终于支持多个path了,刚开始代码纯粹靠堆起来的,有空再完善

已经玩坏了~
[url=][/url]

TOP



已经NB上天了。
去学去写去用才有进步。安装python3代码存为xx.py 双击运行或右键用IDLE打开按F5运行

TOP

返回列表