1# Purpose: acdsdata section manager
2# Created: 05.05.2014
3# Copyright (C) 2014, Manfred Moitzi
4# License: MIT License
5
6from __future__ import unicode_literals
7__author__ = "mozman <mozman@gmx.at>"
8
9from itertools import islice
10from .tags import TagGroups, DXFStructureError, Tags, binary_encoded_data_to_bytes
11
12
13class AcDsDataSection(object):
14    name = 'acdsdata'
15
16    def __init__(self):
17        # Standard_ACIS_Binary (SAB) data store, key = handle of DXF Entity in the ENTITIES section: BODY, 3DSOLID
18        # SURFACE, PLANESURFACE, REGION
19        self.sab_data = {}
20
21    @classmethod
22    def from_tags(cls, tags, drawing):
23        data_section = cls()
24        data_section._build(tags)
25        return data_section
26
27    def _build(self, tags):
28        if len(tags) == 3:  # empty entities section
29            return
30
31        for group in TagGroups(islice(tags, 2, len(tags)-1)):
32            data_record = AcDsDataRecord(Tags(group))
33            if data_record.dxftype == 'ACDSRECORD':
34                asm_data = data_record.get_section('ASM_Data', None)
35                if asm_data is not None:
36                    self.add_asm_data(data_record)
37
38    def add_asm_data(self, acdsrecord):
39        """ Store SAB data as binary string in the sab_data dict, with handle to owner Entity as key.
40        """
41        try:
42            asm_data = acdsrecord.get_section('ASM_Data')
43            entity_id = acdsrecord.get_section('AcDbDs::ID')
44        except ValueError:
45            return
46        else:
47            handle = entity_id[2].value
48            binary_data_text = (tag.value for tag in asm_data if tag.code == 310)
49            binary_data = binary_encoded_data_to_bytes(binary_data_text)
50            self.sab_data[handle] = binary_data
51
52
53class Section(Tags):
54    @property
55    def name(self):
56        return self[0].value
57
58    @property
59    def type(self):
60        return self[1].value
61
62    @property
63    def data(self):
64        return self[2:]
65
66
67class AcDsDataRecord(object):
68    def __init__(self, tags):
69        self.dxftype = tags[0].value
70        start_index = 2
71        while tags[start_index].code != 2:
72            start_index += 1
73        self.sections = [Section(tags) for tags in TagGroups(islice(tags, start_index, None), split_code=2)]
74
75    def has_section(self, name):
76        return self.get_section(name, default=None) is not None
77
78    def get_section(self, name, default=KeyError):
79        for section in self.sections:
80            if section.name == name:
81                return section
82        if default is KeyError:
83            raise KeyError(name)
84        else:
85            return default
86
87    def __getitem__(self, name):
88        return self.get_section(name)
89