157 lines
4.3 KiB
Perl
157 lines
4.3 KiB
Perl
package Manticore::Layer;
|
|
|
|
# package for internal handling and processing of layers
|
|
|
|
# A layer contains an internal representation of data
|
|
# It renders into a list of objects, which are one of
|
|
# * non-selfoverlapping polygons with abstract color
|
|
# * Named lines
|
|
# * Named points
|
|
# * Named float values
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Manticore::Layer::Traverse;
|
|
|
|
# Data representation:
|
|
# {
|
|
# data => internal data format
|
|
# srcdata => string data representation
|
|
# mode => kind of the layer
|
|
# children => child layers
|
|
# };
|
|
|
|
# renderMode, each entry:
|
|
# convert -- return the polynomials from the data and sub-layers
|
|
# parse -- what we parse; either everything or blockwise
|
|
# parsemode -- do we parse blockwise (that is: whitespace free sequences thay may contain whitespace in (), but these may only contain matching ()s) or total
|
|
# serialize -- reverse of parse; not neccessary if data modification by other methods is not meant to happen
|
|
# desc -- description text
|
|
# children -- meant to have child layers
|
|
# implementby -- implementation of most stuff by a submodule
|
|
|
|
my %renderMode = (
|
|
traverse => {
|
|
#convert => sub {},
|
|
#parse => sub {
|
|
# my $block = shift;
|
|
#},
|
|
parsemode => "blockwise",
|
|
implementby => sub { return Manticore::Layer::Traverse::fromText(@_)},
|
|
desc => 'A closed traverse line defining the object. That can be a polygon or contain additional interpolation primitives.',
|
|
children => 0,
|
|
},
|
|
polynom => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'A polynomial whichs positive set defines the object.',
|
|
children => 0,
|
|
},
|
|
union => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Several layers atop of each other; the higher/earlier layers cover the layers below. It has the color if the color can be seen in the highest layer',
|
|
children => 1,
|
|
},
|
|
intersect => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Several layers atop of each other; color is only there if it is there in every layer and the same.',
|
|
children => 1,
|
|
},
|
|
difference => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Several layers atop of each other; color of the first layer unless any of the further layers has this color as well.',
|
|
children => 1,
|
|
},
|
|
hull => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Convex hull of the object.',
|
|
children => 1,
|
|
},
|
|
sum => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Minkowsky sum of the sub objects.',
|
|
children => 1,
|
|
},
|
|
recol => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "blockwise",
|
|
desc => 'Recolorize the sub objects.',
|
|
children => 1,
|
|
},
|
|
file => {
|
|
convert => sub {},
|
|
parse => sub {},
|
|
parsemode => "everything",
|
|
desc => 'Load the data from an external file.',
|
|
children => 0,
|
|
},
|
|
);
|
|
|
|
# split input into blocks
|
|
sub _splitBlocks {
|
|
my $cont = shift;
|
|
# split into blocks
|
|
# Note: regexes have sub-patterns
|
|
# "aababb"=~m#^(?<AB>|ab|a(?&AB)ba(?&AB)b|a(?&AB)b)$#
|
|
my $remain = $cont;
|
|
my $parsed = "";
|
|
my @all = ();
|
|
while(
|
|
$remain=~s#^(\s+)## ||
|
|
$remain=~s#^((?:[^\s\(\)]+|(?<DYCK>\((?:[^\(\)]+|(?&DYCK))*\)))+)##
|
|
) {
|
|
my $tok = $1;
|
|
$parsed .= $tok;
|
|
push @all, $tok unless $tok=~m#^\s#;
|
|
}
|
|
return { error=>"Could not complete parsing", parsed=> $parsed, remain=>$remain} if $remain;
|
|
return @all
|
|
}
|
|
|
|
sub fromText {
|
|
my (undef, $head, $cont, $children) = @_;
|
|
if(exists $renderMode{$head}) {
|
|
my $render = $renderMode{$head};
|
|
my @all = ($cont);
|
|
if('blockwise' eq $render->{parsemode}) {
|
|
@all = _splitBlocks($cont);
|
|
if('HASH' eq ref $all[0]) {
|
|
return $all[0]
|
|
}
|
|
}
|
|
if($render->{implementby}) {
|
|
return $render->{implementby}->(@all);
|
|
}
|
|
my $data = $render->{parse}->(@all);
|
|
return { error => "Could not parse input" } unless $data;
|
|
if($data and 'HASH' eq ref $data and $data->{error}) {
|
|
return { error => "Parse error: $data->{error}" }
|
|
}
|
|
my %h = (
|
|
data => $data,
|
|
srcdata => $cont,
|
|
mode => $head,
|
|
);
|
|
$h{children} = $children if $render->{children};
|
|
return bless \%h;
|
|
} else {
|
|
return { error => "Parse mode non-existent: $head"};
|
|
}
|
|
}
|
|
|
|
|
|
1;
|