Skip to content
####################################################################################################
def _qInstallMessageHandler(handler):
'''Install a message handler that works in all bindings
Args:
handler: A function that takes 3 arguments, or None
'''
def messageOutputHandler(*args):
# In Qt5 bindings, message handlers are passed 3 arguments
# The first argument is a QtMsgType
# The last argument is the message to be printed
# The Middle argument (if passed) is a QMessageLogContext
if len(args) == 3:
msgType, logContext, msg = args
elif len(args) == 2:
msgType, msg = args
logContext = None
else:
raise TypeError(
'handler expected 2 or 3 arguments, got {0}'.format(len(args)))
if isinstance(msg, bytes):
# In python 3, some bindings pass a bytestring, which cannot be
# used elsewhere. Decoding a python 2 or 3 bytestring object will
# consistently return a unicode object.
msg = msg.decode()
handler(msgType, logContext, msg)
if not handler:
handler = messageOutputHandler
return Qt._QtCore.qInstallMessageHandler(handler)
"""Minimal Python 3 shim around PyQt5 and Pyside2 Qt bindings for QML applications.
Forked from https://github.com/mottosso/Qt.py under MIT License.
Copyright (c) 2016 Marcus Ottosson
Changes
* Dropped Python2 and Qt4 support
* Focus on last Python 3 release
* Focus on last Qt API : QML
Requirements
* make use of lazy loading to speed up startup time !
"""
# Fixme: ressource file Patro/QtApplication/rcc/PatroRessource.py
####################################################################################################
# Enable support for `from Qt import *`
__all__ = []
####################################################################################################
import importlib
import logging
import os
import sys
import types
from .QtConfig import _common_members, _misplaced_members, _compatibility_members
####################################################################################################
# _module_logger = logging.getLogger(__name__)
####################################################################################################
# Flags from environment variables
QT_VERBOSE = bool(os.getenv('QT_VERBOSE'))
QT_PREFERRED_BINDING = os.getenv('QT_PREFERRED_BINDING', '')
if QT_PREFERRED_BINDING:
QT_PREFERRED_BINDING = list(x for x in QT_PREFERRED_BINDING.split(',') if x)
else:
# on dec 2018, PySide2 is still not fully operational
QT_PREFERRED_BINDING = ('PyQt5', 'PySide2')
####################################################################################################
def _new_module(name):
return types.ModuleType(__name__ + '.' + name)
####################################################################################################
# Reference to Qt.py
Qt = sys.modules[__name__]
Qt.QtCompat = _new_module('QtCompat')
####################################################################################################
def _log(text):
if QT_VERBOSE:
# _logger print
sys.stdout.write(text + '\n')
####################################################################################################
def _import_sub_module(module, name):
"""import a submodule"""
_log('_import_sub_module {} {}'.format(module, name))
module_name = module.__name__ + '.' + name # e.g. PyQt5.QtCore
module = importlib.import_module(module_name)
return module
####################################################################################################
def _setup(module, extras):
"""Install common submodules"""
Qt.__binding__ = module.__name__
for name in list(_common_members) + extras:
try:
submodule = _import_sub_module(module, name)
except ImportError:
try:
# For extra modules like sip and shiboken that may not be
# children of the binding.
submodule = __import__(name)
except ImportError:
continue
setattr(Qt, '_' + name, submodule)
if name not in extras:
# Store reference to original binding
setattr(Qt, name, _new_module(name)) # Qt.QtCore = module(so module)
####################################################################################################
def _reassign_misplaced_members(binding):
"""Apply misplaced members from `binding` to Qt.py
Arguments:
binding (dict): Misplaced members
"""
for src, dst in _misplaced_members[binding].items():
# print()
dst_value = None
# Fixme: to func
src_parts = src.split('.')
src_module = src_parts[0]
if len(src_parts):
src_member = src_parts[1:]
else:
src_member = None
if isinstance(dst, (list, tuple)):
dst, dst_value = dst
# print(src, '->', dst, dst_value)
# print(src_module, src_member)
dst_parts = dst.split('.')
dst_module = dst_parts[0]
if len(dst_parts):
dst_member = dst_parts[1]
else:
dst_member = None
# print(dst_module, dst_member)
# Get the member we want to store in the namesapce.
if not dst_value:
try:
_part = getattr(Qt, '_' + src_module)
while src_member:
member = src_member.pop(0)
_part = getattr(_part, member)
dst_value = _part
except AttributeError:
# If the member we want to store in the namespace does not
# exist, there is no need to continue. This can happen if a
# request was made to rename a member that didn't exist, for
# example if QtWidgets isn't available on the target platform.
_log('Misplaced member has no source: {0}'.format(src))
continue
# print(dst_value)
try:
# Fixme: src_object ???
src_object = getattr(Qt, dst_module)
except AttributeError:
# print('Failed to get src_object')
if dst_module not in _common_members:
# Only create the Qt parent module if its listed in
# _common_members. Without this check, if you remove QtCore
# from _common_members, the default _misplaced_members will add
# Qt.QtCore so it can add Signal, Slot, etc.
msg = "Not creating missing member module '{m}' for '{c}'"
_log(msg.format(m=dst_module, c=dst_member))
continue
# If the dst is valid but the Qt parent module does not exist
# then go ahead and create a new module to contain the member.
setattr(Qt, dst_module, _new_module(dst_module))
src_object = getattr(Qt, dst_module)
# Enable direct import of the new module
sys.modules[__name__ + '.' + dst_module] = src_object
if not dst_value:
dst_value = getattr(Qt, '_' + src_module)
if src_member:
dst_value = getattr(dst_value, src_member)
setattr(
src_object,
dst_member or dst_module,
dst_value
)
####################################################################################################
def _build_compatibility_members(binding, decorators=None):
"""Apply `binding` to QtCompat
Arguments:
binding (str): Top level binding in _compatibility_members.
decorators (dict, optional): Provides the ability to decorate the
original Qt methods when needed by a binding. This can be used
to change the returned value to a standard value. The key should
be the classname, the value is a dict where the keys are the
target method names, and the values are the decorator functions.
"""
decorators = decorators or dict()
# Allow optional site-level customization of the compatibility members.
# This method does not need to be implemented in QtSiteConfig.
try:
import QtSiteConfig
except ImportError:
pass
else:
if hasattr(QtSiteConfig, 'update_compatibility_decorators'):
QtSiteConfig.update_compatibility_decorators(binding, decorators)
_QtCompat = type('QtCompat', (object,), {})
for classname, bindings in _compatibility_members[binding].items():
attrs = {}
for target, binding in bindings.items():
namespaces = binding.split('.')
try:
src_object = getattr(Qt, '_' + namespaces[0])
except AttributeError as e:
_log('QtCompat: AttributeError: %s' % e)
# Skip reassignment of non-existing members.
# This can happen if a request was made to
# rename a member that didn't exist, for example
# if QtWidgets isn't available on the target platform.
continue
# Walk down any remaining namespace getting the object assuming
# that if the first namespace exists the rest will exist.
for namespace in namespaces[1:]:
src_object = getattr(src_object, namespace)
# decorate the Qt method if a decorator was provided.
if target in decorators.get(classname, []):
# staticmethod must be called on the decorated method to
# prevent a TypeError being raised when the decorated method
# is called.
src_object = staticmethod(
decorators[classname][target](src_object))
attrs[target] = src_object
# Create the QtCompat class and install it into the namespace
compat_class = type(classname, (_QtCompat,), attrs)
setattr(Qt.QtCompat, classname, compat_class)
####################################################################################################
def _pyside2():
"""Initialise PySide2
These functions serve to test the existence of a binding
along with set it up in such a way that it aligns with
the final step; adding members from the original binding
to Qt.py
"""
import PySide2 as module
extras = []
# try:
# from PySide2 import shiboken2
# extras.append('shiboken2')
# except ImportError:
# pass
_setup(module, extras)
Qt.__binding_version__ = module.__version__
# if hasattr(Qt, '_shiboken2'):
# Qt.QtCompat.wrapInstance = _wrapinstance
# Qt.QtCompat.getCppPointer = _getcpppointer
# Qt.QtCompat.delete = shiboken2.delete
if hasattr(Qt, '_QtCore'):
Qt.__qt_version__ = Qt._QtCore.qVersion()
# if hasattr(Qt, '_QtWidgets'):
# Qt.QtCompat.setSectionResizeMode = \
# Qt._QtWidgets.QHeaderView.setSectionResizeMode
_reassign_misplaced_members('PySide2')
# _build_compatibility_members('PySide2')
####################################################################################################
def _pyqt5():
"""Initialise PyQt5"""
import PyQt5 as module
extras = []
# try:
# import sip
# extras.append(sip.__name__)
# except ImportError:
# sip = None
_setup(module, extras)
# if hasattr(Qt, '_sip'):
# Qt.QtCompat.wrapInstance = _wrapinstance
# Qt.QtCompat.getCppPointer = _getcpppointer
# Qt.QtCompat.delete = sip.delete
if hasattr(Qt, '_QtCore'):
Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
# if hasattr(Qt, '_QtWidgets'):
# Qt.QtCompat.setSectionResizeMode = \
# Qt._QtWidgets.QHeaderView.setSectionResizeMode
_reassign_misplaced_members('PyQt5')
# _build_compatibility_members('PyQt5')
####################################################################################################
def _install():
# Default order (customise order and content via QT_PREFERRED_BINDING)
order = QT_PREFERRED_BINDING
available = {
'PySide2': _pyside2,
'PyQt5': _pyqt5,
}
_log("Order: {}".format(' '.join(order)))
found_binding = False
for name in order:
_log('Trying %s' % name)
try:
available[name]()
found_binding = True
break
except ImportError as e:
_log('ImportError: %s' % e)
except KeyError:
_log("ImportError: Preferred binding '%s' not found." % name)
if not found_binding:
# If not binding were found, throw this error
raise ImportError('No Qt binding were found.')
# Install individual members
for name, members in _common_members.items():
try:
their_submodule = getattr(Qt, '_' + name)
except AttributeError:
continue
our_submodule = getattr(Qt, name)
# Enable import *
__all__.append(name)
# Enable direct import of submodule,
# e.g. import Qt.QtCore
sys.modules[__name__ + '.' + name] = our_submodule
for member in members:
# Accept that a submodule may miss certain members.
try:
their_member = getattr(their_submodule, member)
except AttributeError:
_log("'%s.%s' was missing." % (name, member))
continue
setattr(our_submodule, member, their_member)
# Enable direct import of QtCompat
sys.modules['Qt.QtCompat'] = Qt.QtCompat
####################################################################################################
_install()
####################################################################################################
# Fixme: Python 3.7
# def __getattr__(name):
# print('__getattr__', name)
####################################################################################################
# Setup Binding Enum states
Qt.IsPySide2 = Qt.__binding__ == 'PySide2'
Qt.IsPyQt5 = not Qt.IsPySide2
####################################################################################################
def _getcpppointer(object):
if hasattr(Qt, '_shiboken2'):
return getattr(Qt, '_shiboken2').getCppPointer(object)[0]
elif hasattr(Qt, '_sip'):
return getattr(Qt, '_sip').unwrapinstance(object)
raise AttributeError("'module' has no attribute 'getCppPointer'")
####################################################################################################
def _wrapinstance(ptr, base=None):
'''Enable implicit cast of pointer to most suitable class
This behaviour is available in sip per default.
Based on http://nathanhorne.com/pyqtpyside-wrap-instance
Usage:
This mechanism kicks in under these circumstances.
1. Qt.py is using PySide 1 or 2.
2. A `base` argument is not provided.
See :func:`QtCompat.wrapInstance()`
Arguments:
ptr (int): Pointer to QObject in memory
base (QObject, optional): Base class to wrap with. Defaults to QObject,
which should handle anything.
'''
assert isinstance(ptr, int), "Argument 'ptr' must be of type <int>"
assert (base is None) or issubclass(base, Qt.QtCore.QObject), (
"Argument 'base' must be of type <QObject>")
if Qt.IsPyQt4 or Qt.IsPyQt5:
func = getattr(Qt, '_sip').wrapinstance
elif Qt.IsPySide2:
func = getattr(Qt, '_shiboken2').wrapInstance
elif Qt.IsPySide:
func = getattr(Qt, '_shiboken').wrapInstance
else:
raise AttributeError("'module' has no attribute 'wrapInstance'")
if base is None:
q_object = func(int(ptr), Qt.QtCore.QObject)
meta_object = q_object.metaObject()
class_name = meta_object.className()
super_class_name = meta_object.superClass().className()
if hasattr(Qt.QtWidgets, class_name):
base = getattr(Qt.QtWidgets, class_name)
elif hasattr(Qt.QtWidgets, super_class_name):
base = getattr(Qt.QtWidgets, super_class_name)
else:
base = Qt.QtCore.QObject
return func(int(ptr), base)
####################################################################################################
def _translate(context, sourceText, *args):
# In Qt4 bindings, translate can be passed 2 or 3 arguments
# In Qt5 bindings, translate can be passed 2 arguments
# The first argument is disambiguation[str]
# The last argument is n[int]
# The middle argument can be encoding[QtCore.QCoreApplication.Encoding]
if len(args) == 3:
disambiguation, encoding, n = args
elif len(args) == 2:
disambiguation, n = args
encoding = None
else:
raise TypeError(
'Expected 4 or 5 arguments, got {0}.'.format(len(args) + 2))
if hasattr(Qt.QtCore, 'QCoreApplication'):
app = getattr(Qt.QtCore, 'QCoreApplication')
else:
raise NotImplementedError(
'Missing QCoreApplication implementation for {binding}'.format(
binding=Qt.__binding__,
)
)
if Qt.__binding__ in ('PySide2', 'PyQt5'):
sanitized_args = [context, sourceText, disambiguation, n]
else:
sanitized_args = [
context,
sourceText,
disambiguation,
encoding or app.CodecForTr,
n
]
return app.translate(*sanitized_args)
####################################################################################################
####################################################################################################
def _none():
'''Internal option (used in installer)'''
Mock = type('Mock', (), {'__getattr__': lambda Qt, attr: None})
Qt.__binding__ = 'None'
Qt.__qt_version__ = '0.0.0'
Qt.__binding_version__ = '0.0.0'
Qt.QtCompat.loadUi = lambda uifile, baseinstance=None: None
Qt.QtCompat.setSectionResizeMode = lambda *args, **kwargs: None
for submodule in _common_members.keys():
setattr(Qt, submodule, Mock())
setattr(Qt, '_' + submodule, Mock())
......@@ -66,6 +66,9 @@
.. https://img.shields.io/github/stars/badges/shields.svg?style=social&label=Star
.. -*- Mode: rst -*-
.. |ezdxf| replace:: ezdxf
.. _ezdxf: https://ezdxf.readthedocs.io/en/latest
.. |Inkscape| replace:: Inkscape
.. _Inkscape: https://inkscape.org
......
#! /usr/bin/env python3
####################################################################################################
#
# Patro - A Python library to make patterns for fashion design
# Copyright (C) 2017 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################
####################################################################################################
from Patro.Common.Logging import Logging
Logging.setup_logging()
####################################################################################################
from Patro.QtApplication.QmlApplication import Application
####################################################################################################
# application = Application()
Application.setup_gui_application()
application = Application.create()
application.exec_()
......@@ -23,8 +23,8 @@ How to get help or report an issue ?
.. List for announcements regarding Patro releases and development
.. `Devel List <https://groups.google.com/forum/#!forum/Patro-devel>`_
.. List for developers of Patro
..
.. **If you encounter an issue, please fill an issue** on the `Issue Tracker <https://github.com/FabriceSalvaire/Patro/issues>`_.
..
**If you encounter an issue, please fill an issue** on the `Issue Tracker <https://github.com/FabriceSalvaire/Patro/issues>`_.
.. (*) Despite Google Groups has many drawbacks, I don't have actually enough resources to run GNU Mailman or
.. Discourse on my own IT infrastructure.
......@@ -16,9 +16,11 @@ Patro implements several components:
* import of SVG pattern (as well as PDF using a conversion tools like |Inkscape|_)
* digitalisation of patterns acquired with a camera **ACTUALLY NOT RELEASED WITH OPEN SOURCE LICENCE**
.. note:: Patro is just a core engine actually. It doesn't implement a GUI similar to |Valentina|_.
.. note:: Patro is just a core engine actually. It doesn't implement a full featured GUI similar to
|Valentina|_.
.. note:: Patro doesn't implement 3D feature actually, like automatic clothe fitting on avatar and tension map.
.. note:: Patro doesn't implement 3D feature actually, like automatic clothe fitting on avatar and
tension map.
Geometry Engine
===============
......@@ -28,10 +30,13 @@ The geometry engine implements:
* 2D vector and usual transformations
* usual 2D primitives:
* point, segment, line
* point, segment, line, polyline
* triangle, rectangle, polygon
* circle and conic
* circle and ellipse
* quadratic and cubic Bézier curve
* B-spline curve
* path made of linear segments with an optional bulge at breaks, as well as quadratic and cubic
Bézier curve segments.
* perimeter and area
* primitive intersection
......@@ -40,30 +45,47 @@ The geometry engine implements:
Pattern Engine
==============
* Measurements can be imported from Valentina *.vit* or a YAML file. We can merge several files to a measurement set.
* Measurements can be imported from Valentina *.vit* or a YAML file. We can merge several files to
a measurement set.
* Measurements are lazily evaluated using |Sympy|_ symbolic computation, which means we can compute
exact values and the order of definition doesn't matter.
Graphic Engine
==============
* show drawing on screen with : |Matplotlib|_
Patro features a basic |Qt|_ user interface which can display a graphic scene and features item
selection so as to provide the minimum to work with.
The graphic engine implement a 2D graphic scene which is rendered by a painter. A scene contains
graphic items like text, image line, circle and Bézier curve.
A painter is responsible to render the scene on the screen or a graphic file format. The graphic
engine is able to render on the following:
* show drawing on screen with : |Matplotlib|_, |Qt|_
* export drawing to : PDF, SVG, DXF, LaTeX Tikz
* export tiled pattern on A4 sheets : PDF, LaTeX Tikz
Also the graphic engine is able to render a DXF made of these graphic items: line, circle, arc,
ellipse, lwpolyline and spline.
Implementation details:
* PDF export is implemented with the help of the |Reportlab|_ package
* DXF export is implemented with the help of the |ezdxf|_ package of `Manfred Moitzi <https://github.com/mozman>`_
* DXF import/export is implemented with the help of the |ezdxf|_ package of `Manfred Moitzi
<https://github.com/mozman>`_
Pattern Format Support
======================
* |Valentina|_ format: read/write *.val* and *.vit* file, but partially implemented, cf. supra for details
* import pattern from SVG
* **DXF is not yet supported**
* import pattern from SVG and DXF (**partially implemented**)
.. note:: PDF and SVG format are convertible to each other without data loss
(font handling require more attention).
.. note:: The |Inkscape|_ free software is able to import a lot of file formats like PDF, DXF and to save it to SVG.
.. note:: The |Inkscape|_ free software is able to import a lot of file formats like PDF, DXF and to
save it to SVG.
Pattern Format Compatibility
----------------------------
......
999
dxflib 3.17.0.0
0
SECTION
2
HEADER
9
$ACADVER
1
AC1015
9
$HANDSEED
5
FFFF
9
$DIMADEC
70
0
9
$DIMASZ
40
2.5
9
$DIMAUNIT
70
0
9
$DIMAZIN
70
2
9
$DIMDEC
70
4
9
$DIMDSEP
70
46
9
$DIMEXE
40
1.25
9
$DIMEXO
40
0.625
9
$DIMGAP
40
0.625
9
$DIMLUNIT
70
2
9
$DIMSCALE
40
1.0
9
$DIMTSZ
40
0.0
9
$DIMTXT
40
2.5
9
$DIMZIN
70
8
9
$DWGCODEPAGE
3
ANSI_1252
9
$INSUNITS
70
4
9
$LTSCALE
40
1.0
9
$MAXACTVP
70
64
9
$MEASUREMENT
70
1
9
$PDMODE
70
0
9
$PDSIZE
40
0.0
0
ENDSEC
0
SECTION
2
TABLES
0
TABLE
2
VPORT
5
8
100
AcDbSymbolTable
70
1
0
VPORT
5
30
100
AcDbSymbolTableRecord
100
AcDbViewportTableRecord
2
*Active
70
0
10
0.0
20
0.0
11
1.0
21
1.0
12
286.3055555555554861
22
148.5
13
0.0
23
0.0
14
10.0
24
10.0
15
10.0
25
10.0
16
0.0
26
0.0
36
1.0
17
0.0
27
0.0
37
0.0
40
297.0
41
1.92798353909465
42
50.0
43
0.0
44
0.0
50
0.0
51
0.0
71
0
72
100
73
1
74
3
75
1
76
1
77
0
78
0
281
0
65
1
110
0.0
120
0.0
130
0.0
111
1.0
121
0.0
131
0.0
112
0.0
122
1.0
132
0.0
79
0
146
0.0
0
ENDTAB
0
TABLE
2
LTYPE
5
5
100
AcDbSymbolTable
70
41
0
LTYPE
5
16
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
Continuous
70
0
3
Solid line
72
65
73
0
40
0.0
0
LTYPE
5
31
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHDOT2
70
0
3
Dash dot (.5x) _._._._._._._._._._._._._._._.
72
65
73
4
40
12.6999999999999993
49
6.3499999999999996
74
0
49
-3.125
74
0
49
0.1
74
0
49
-3.125
74
0
0
LTYPE
5
32
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO13W100
70
0
3
ISO double-dash double-dot __ __ . . __ __ . . _
72
65
73
8
40
36.0000000000000071
49
12.0
74
0
49
-3.0
74
0
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
33
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
BORDER
70
0
3
Border __ __ . __ __ . __ __ . __ __ . __ __ .
72
65
73
6
40
44.4499999999999957
49
12.6999999999999993
74
0
49
-6.3499999999999996
74
0
49
12.6999999999999993
74
0
49
-6.2999999999999998
74
0
49
0.1
74
0
49
-6.2999999999999998
74
0
0
LTYPE
5
14
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
BYBLOCK
70
0
3
72
65
73
0
40
0.0
0
LTYPE
5
34
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
HIDDEN2
70
0
3
Hidden (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
72
65
73
2
40
4.7624999999999993
49
3.1749999999999998
74
0
49
-1.5874999999999999
74
0
0
LTYPE
5
35
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DIVIDE2
70
0
3
Divide (.5x) __..__..__..__..__..__..__..__.._
72
65
73
6
40
15.8749999999999982
49
6.3499999999999996
74
0
49
-3.125
74
0
49
0.1
74
0
49
-3.0750000000000002
74
0
49
0.1
74
0
49
-3.125
74
0
0
LTYPE
5
36
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DOT
70
0
3
Dot . . . . . . . . . . . . . . . . . . . . . . . .
72
65
73
2
40
6.3499999999999996
49
0.1
74
0
49
-6.25
74
0
0
LTYPE
5
37
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHEDX2
70
0
3
Dashed (2x) ____ ____ ____ ____ ____ ___
72
65
73
2
40
38.0999999999999943
49
25.3999999999999986
74
0
49
-12.6999999999999993
74
0
0
LTYPE
5
38
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DIVIDEX2
70
0
3
Divide (2x) ________ . . ________ . . _
72
65
73
6
40
63.5
49
25.3999999999999986
74
0
49
-12.6499999999999986
74
0
49
0.1
74
0
49
-12.5999999999999979
74
0
49
0.1
74
0
49
-12.6499999999999986
74
0
0
LTYPE
5
39
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
PHANTOM2
70
0
3
Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _
72
65
73
6
40
31.7500000000000036
49
15.875
74
0
49
-3.1749999999999998
74
0
49
3.1749999999999998
74
0
49
-3.1749999999999998
74
0
49
3.1749999999999998
74
0
49
-3.1749999999999998
74
0
0
LTYPE
5
3A
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
PHANTOMX2
70
0
3
Phantom (2x) ____________ ____ ____ _
72
65
73
6
40
127.0000000000000142
49
63.5
74
0
49
-12.6999999999999993
74
0
49
12.6999999999999993
74
0
49
-12.6999999999999993
74
0
49
12.6999999999999993
74
0
49
-12.6999999999999993
74
0
0
LTYPE
5
3B
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
HIDDENX2
70
0
3
Hidden (2x) ____ ____ ____ ____ ____ ____ ____
72
65
73
2
40
19.0499999999999972
49
12.6999999999999993
74
0
49
-6.3499999999999996
74
0
0
LTYPE
5
3C
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DIVIDE
70
0
3
Divide ____ . . ____ . . ____ . . ____ . . ____
72
65
73
6
40
31.7500000000000036
49
12.6999999999999993
74
0
49
-6.2999999999999998
74
0
49
0.1
74
0
49
-6.25
74
0
49
0.1
74
0
49
-6.2999999999999998
74
0
0
LTYPE
5
3D
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
CENTER
70
0
3
Center ____ _ ____ _ ____ _ ____ _ ____ _ ____
72
65
73
4
40
50.8000000000000043
49
31.75
74
0
49
-6.3499999999999996
74
0
49
6.3499999999999996
74
0
49
-6.3499999999999996
74
0
0
LTYPE
5
3E
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO14W100
70
0
3
ISO dash triple-dot __ . . . __ . . . __ . . . _
72
65
73
8
40
24.0000000000000036
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
3F
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO02W100
70
0
3
ISO dash __ __ __ __ __ __ __ __ __ __ __ __ __
72
65
73
2
40
15.0
49
12.0
74
0
49
-3.0
74
0
0
LTYPE
5
40
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO10W100
70
0
3
ISO dash dot __ . __ . __ . __ . __ . __ . __ .
72
65
73
4
40
18.0
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
41
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
BORDERX2
70
0
3
Border (2x) ____ ____ . ____ ____ . ___
72
65
73
6
40
88.8999999999999773
49
25.3999999999999986
74
0
49
-12.6999999999999993
74
0
49
25.3999999999999986
74
0
49
-12.6499999999999986
74
0
49
0.1
74
0
49
-12.6499999999999986
74
0
0
LTYPE
5
42
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
PHANTOM
70
0
3
Phantom ______ __ __ ______ __ __ ______
72
65
73
6
40
63.5000000000000071
49
31.75
74
0
49
-6.3499999999999996
74
0
49
6.3499999999999996
74
0
49
-6.3499999999999996
74
0
49
6.3499999999999996
74
0
49
-6.3499999999999996
74
0
0
LTYPE
5
43
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO07W100
70
0
3
ISO dot . . . . . . . . . . . . . . . . . . . .
72
65
73
2
40
3.0
49
0.1
74
0
49
-2.8999999999999999
74
0
0
LTYPE
5
44
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO15W100
70
0
3
ISO double-dash triple-dot __ __ . . . __ __ . .
72
65
73
10
40
39.0000000000000071
49
12.0
74
0
49
-3.0
74
0
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
45
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
HIDDEN
70
0
3
Hidden __ __ __ __ __ __ __ __ __ __ __ __ __ __
72
65
73
2
40
9.5249999999999986
49
6.3499999999999996
74
0
49
-3.1749999999999998
74
0
0
LTYPE
5
46
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
CENTERX2
70
0
3
Center (2x) ________ __ ________ __ _____
72
65
73
4
40
101.6000000000000085
49
63.5
74
0
49
-12.6999999999999993
74
0
49
12.6999999999999993
74
0
49
-12.6999999999999993
74
0
0
LTYPE
5
47
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO08W100
70
0
3
ISO long-dash short-dash ____ __ ____ __ ____ _
72
65
73
4
40
36.0
49
24.0
74
0
49
-3.0
74
0
49
6.0
74
0
49
-3.0
74
0
0
LTYPE
5
48
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO11W100
70
0
3
ISO double-dash dot __ __ . __ __ . __ __ . __ _
72
65
73
6
40
33.0
49
12.0
74
0
49
-3.0
74
0
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
49
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
BORDER2
70
0
3
Border (.5x) __.__.__.__.__.__.__.__.__.__.__.
72
65
73
6
40
22.2250000000000014
49
6.3499999999999996
74
0
49
-3.1749999999999998
74
0
49
6.3499999999999996
74
0
49
-3.125
74
0
49
0.1
74
0
49
-3.125
74
0
0
LTYPE
5
4A
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DOTX2
70
0
3
Dot (2x) . . . . . . . . . . . . . .
72
65
73
2
40
12.6999999999999993
49
0.1
74
0
49
-12.5999999999999996
74
0
0
LTYPE
5
4B
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
CENTER2
70
0
3
Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___
72
65
73
4
40
28.5750000000000028
49
19.0500000000000007
74
0
49
-3.1749999999999998
74
0
49
3.1749999999999998
74
0
49
-3.1749999999999998
74
0
0
LTYPE
5
4C
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO03W100
70
0
3
ISO dash space __ __ __ __ __ __
72
65
73
2
40
30.0
49
12.0
74
0
49
-18.0
74
0
0
LTYPE
5
4D
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHDOT
70
0
3
Dash dot __ . __ . __ . __ . __ . __ . __ . __
72
65
73
4
40
25.4000000000000021
49
12.6999999999999993
74
0
49
-6.2999999999999998
74
0
49
0.1
74
0
49
-6.2999999999999998
74
0
0
LTYPE
5
4E
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHDOTX2
70
0
3
Dash dot (2x) ____ . ____ . ____ . ___
72
65
73
4
40
50.7999999999999972
49
25.3999999999999986
74
0
49
-12.6499999999999986
74
0
49
0.1
74
0
49
-12.6499999999999986
74
0
0
LTYPE
5
4F
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO04W100
70
0
3
ISO long-dash dot ____ . ____ . ____ . ____ . _
72
65
73
4
40
30.0
49
24.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
50
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO09W100
70
0
3
ISO long-dash double-short-dash ____ __ __ ____
72
65
73
6
40
45.0
49
24.0
74
0
49
-3.0
74
0
49
6.0
74
0
49
-3.0
74
0
49
6.0
74
0
49
-3.0
74
0
0
LTYPE
5
51
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DOT2
70
0
3
Dot (.5x) ........................................
72
65
73
2
40
3.1749999999999998
49
0.1
74
0
49
-3.0749999999999997
74
0
0
LTYPE
5
15
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
BYLAYER
70
0
3
72
65
73
0
40
0.0
0
LTYPE
5
52
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO05W100
70
0
3
ISO long-dash double-dot ____ .. ____ .. ____ .
72
65
73
6
40
33.0000000000000071
49
24.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
53
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO12W100
70
0
3
ISO dash double-dot __ . . __ . . __ . . __ . .
72
65
73
6
40
21.0
49
12.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
LTYPE
5
54
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHED2
70
0
3
Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
72
65
73
2
40
9.5249999999999986
49
6.3499999999999996
74
0
49
-3.1749999999999998
74
0
0
LTYPE
5
55
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
DASHED
70
0
3
Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _
72
65
73
2
40
19.0499999999999972
49
12.6999999999999993
74
0
49
-6.3499999999999996
74
0
0
LTYPE
5
56
100
AcDbSymbolTableRecord
100
AcDbLinetypeTableRecord
2
ACAD_ISO06W100
70
0
3
ISO long-dash triple-dot ____ ... ____ ... ____
72
65
73
8
40
36.0000000000000071
49
24.0
74
0
49
-2.9500000000000002
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9000000000000004
74
0
49
0.1
74
0
49
-2.9500000000000002
74
0
0
ENDTAB
0
TABLE
2
LAYER
5
2
100
AcDbSymbolTable
70
1
0
LAYER
5
10
100
AcDbSymbolTableRecord
100
AcDbLayerTableRecord
2
0
70
0
62
7
420
16777215
6
Continuous
370
25
390
F
0
ENDTAB
0
TABLE
2
STYLE
5
3
100
AcDbSymbolTable
70
1
0
STYLE
5
57
100
AcDbSymbolTableRecord
100
AcDbTextStyleTableRecord
2
Standard
70
0
40
0.0
41
1.0
50
0.0
71
0
42
2.5
3
4
1001
ACAD
1000
txt
1071
0
0
ENDTAB
0
TABLE
2
VIEW
5
6
100
AcDbSymbolTable
70
0
0
ENDTAB
0
TABLE
2
UCS
5
7
100
AcDbSymbolTable
70
0
0
ENDTAB
0
TABLE
2
APPID
5
9
100
AcDbSymbolTable
70
1
0
APPID
5
12
100
AcDbSymbolTableRecord
100
AcDbRegAppTableRecord
2
ACAD
70
0
0
APPID
5
58
100
AcDbSymbolTableRecord
100
AcDbRegAppTableRecord
2
QCAD
70
0
0
ENDTAB
0
TABLE
2
DIMSTYLE
5
A
100
AcDbSymbolTable
70
1
100
AcDbDimStyleTable
71
0
0
DIMSTYLE
105
27
100
AcDbSymbolTableRecord
100
AcDbDimStyleTableRecord
2
Standard
41
2.5
42
0.625
43
3.75
44
1.25
70
0
73
0
74
0
77
1
78
8
140
2.5
141
2.5
143
0.03937007874016
147
0.625
171
3
172
1
271
2
272
2
274
3
278
44
283
0
284
8
340
57
0
ENDTAB
0
TABLE
2
BLOCK_RECORD
5
1
100
AcDbSymbolTable
70
1
0
BLOCK_RECORD
5
1F
100
AcDbSymbolTableRecord
100
AcDbBlockTableRecord
2
*Model_Space
340
22
0
BLOCK_RECORD
5
1B
100
AcDbSymbolTableRecord
100
AcDbBlockTableRecord
2
*Paper_Space
340
1E
0
BLOCK_RECORD
5
23
100
AcDbSymbolTableRecord
100
AcDbBlockTableRecord
2
*Paper_Space0
340
26
0
ENDTAB
0
ENDSEC
0
SECTION
2
BLOCKS
0
BLOCK
5
20
100
AcDbEntity
8
0
100
AcDbBlockBegin
2
*Model_Space
70
0
10
0.0
20
0.0
30
0.0
3
*Model_Space
1
0
ENDBLK
5
21
100
AcDbEntity
8
0
100
AcDbBlockEnd
0
BLOCK
5
1C
100
AcDbEntity
67
1
8
0
100
AcDbBlockBegin
2
*Paper_Space
70
0
10
0.0
20
0.0
30
0.0
3
*Paper_Space
1
0
ENDBLK
5
1D
100
AcDbEntity
67
1
8
0
100
AcDbBlockEnd
0
BLOCK
5
24
100
AcDbEntity
8
0
100
AcDbBlockBegin
2
*Paper_Space0
70
0
10
0.0
20
0.0
30
0.0
3
*Paper_Space0
1
0
ENDBLK
5
25
100
AcDbEntity
8
0
100
AcDbBlockEnd
0
ENDSEC
0
SECTION
2
ENTITIES
0
LINE
5
59
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
10.0
20
10.0
30
0.0
11
30.0
21
10.0
31
0.0
0
LINE
5
5A
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
30.0
20
10.0
30
0.0
11
30.0
21
30.0
31
0.0
0
LINE
5
5B
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
30.0
20
30.0
30
0.0
11
10.0
21
30.0
31
0.0
0
LINE
5
5C
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
10.0
20
30.0
30
0.0
11
10.0
21
10.0
31
0.0
0
LINE
5
5D
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
0.0
20
10.0
30
0.0
11
0.0
21
30.0
31
0.0
0
LINE
5
5E
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
10.0
20
50.0
30
0.0
11
10.0
21
60.0
31
0.0
0
LINE
5
5F
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
10.0
20
60.0
30
0.0
11
24.8786796564403545
21
45.1213203435596455
31
0.0
0
LINE
5
60
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbLine
10
22.757359312880709
20
40.0
30
0.0
11
20.0
21
40.0
31
0.0
0
CIRCLE
5
61
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbCircle
10
50.0
20
20.0
30
0.0
40
10.0
0
ELLIPSE
5
62
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbEllipse
10
80.0
20
20.0
30
0.0
11
0.0
21
20.0
31
0.0
40
0.5
41
0.0
42
6.2831853071795862
0
SPLINE
5
63
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbSpline
70
8
71
3
72
11
73
7
74
0
40
0.0
40
0.0
40
0.0
40
0.0
40
1.0
40
2.0
40
3.0
40
4.0
40
4.0
40
4.0
40
4.0
10
40.0
20
50.0
30
0.0
10
49.0
20
60.0
30
0.0
10
60.0
20
50.0
30
0.0
10
70.0
20
40.0
30
0.0
10
80.0
20
60.0
30
0.0
10
100.0
20
60.0
30
0.0
10
100.0
20
60.0
30
0.0
0
ARC
5
64
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbCircle
10
20.0
20
50.0
30
0.0
40
10.0
100
AcDbArc
50
180.0
51
270.0
0
ARC
5
65
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbCircle
10
22.757359312880709
20
43.0
30
0.0
40
3.0
100
AcDbArc
50
270.0
51
45.0
0
LWPOLYLINE
5
66
100
AcDbEntity
8
0
62
256
370
-1
48
1.0
6
BYLAYER
100
AcDbPolyline
90
6
70
0
10
100.0
20
50.0
10
92.1213203435596455
20
42.1213203435596455
42
0.414213562373095
10
92.1213203435596455
20
37.8786796564403545
10
100.0
20
30.0
10
100.0
20
20.0
10
110.0
20
10.0
0
ENDSEC
0
SECTION
2
OBJECTS
0
DICTIONARY
5
C
100
AcDbDictionary
280
0
281
1
3
ACAD_GROUP
350
D
3
ACAD_LAYOUT
350
1A
3
ACAD_MLINESTYLE
350
17
3
ACAD_PLOTSETTINGS
350
19
3
ACAD_PLOTSTYLENAME
350
E
3
AcDbVariableDictionary
350
67
3
QCAD_OBJECTS
350
68
0
DICTIONARY
5
D
100
AcDbDictionary
280
0
281
1
0
ACDBDICTIONARYWDFLT
5
E
100
AcDbDictionary
281
1
3
Normal
350
F
100
AcDbDictionaryWithDefault
340
F
0
ACDBPLACEHOLDER
5
F
0
DICTIONARY
5
17
100
AcDbDictionary
280
0
281
1
3
Standard
350
18
0
MLINESTYLE
5
18
100
AcDbMlineStyle
2
STANDARD
70
0
3
62
256
51
90.0
52
90.0
71
2
49
0.5
62
256
6
BYLAYER
49
-0.5
62
256
6
BYLAYER
0
DICTIONARY
5
19
100
AcDbDictionary
280
0
281
1
0
DICTIONARY
5
1A
100
AcDbDictionary
281
1
3
Layout1
350
1E
3
Layout2
350
26
3
Model
350
22
0
LAYOUT
5
1E
100
AcDbPlotSettings
1
2
none_device
4
6
40
0.0
41
0.0
42
0.0
43
0.0
44
0.0
45
0.0
46
0.0
47
0.0
48
0.0
49
0.0
140
0.0
141
0.0
142
1.0
143
1.0
70
688
72
0
73
0
74
5
7
75
16
147
1.0
148
0.0
149
0.0
100
AcDbLayout
1
Layout1
70
1
71
1
10
0.0
20
0.0
11
420.0
21
297.0
12
0.0
22
0.0
32
0.0
14
100000000000000000000.0
24
100000000000000000000.0
34
100000000000000000000.0
15
-100000000000000000000.0
25
-100000000000000000000.0
35
-100000000000000000000.0
146
0.0
13
0.0
23
0.0
33
0.0
16
1.0
26
0.0
36
0.0
17
0.0
27
1.0
37
0.0
76
0
330
1B
0
LAYOUT
5
22
100
AcDbPlotSettings
1
2
none_device
4
6
40
0.0
41
0.0
42
0.0
43
0.0
44
0.0
45
0.0
46
0.0
47
0.0
48
0.0
49
0.0
140
0.0
141
0.0
142
1.0
143
1.0
70
1712
72
0
73
0
74
0
7
75
0
147
1.0
148
0.0
149
0.0
100
AcDbLayout
1
Model
70
1
71
0
10
0.0
20
0.0
11
12.0
21
9.0
12
0.0
22
0.0
32
0.0
14
0.0
24
0.0
34
0.0
15
0.0
25
0.0
35
0.0
146
0.0
13
0.0
23
0.0
33
0.0
16
1.0
26
0.0
36
0.0
17
0.0
27
1.0
37
0.0
76
0
330
1F
0
LAYOUT
5
26
100
AcDbPlotSettings
1
2
none_device
4
6
40
0.0
41
0.0
42
0.0
43
0.0
44
0.0
45
0.0
46
0.0
47
0.0
48
0.0
49
0.0
140
0.0
141
0.0
142
1.0
143
1.0
70
688
72
0
73
0
74
5
7
75
16
147
1.0
148
0.0
149
0.0
100
AcDbLayout
1
Layout2
70
1
71
2
10
0.0
20
0.0
11
12.0
21
9.0
12
0.0
22
0.0
32
0.0
14
0.0
24
0.0
34
0.0
15
0.0
25
0.0
35
0.0
146
0.0
13
0.0
23
0.0
33
0.0
16
1.0
26
0.0
36
0.0
17
0.0
27
1.0
37
0.0
76
0
330
23
0
DICTIONARY
5
67
100
AcDbDictionary
281
1
3
DIMASSOC
350
6A
3
HIDETEXT
350
69
0
DICTIONARYVAR
5
69
100
DictionaryVariables
280
0
1
2
0
DICTIONARYVAR
5
6A
100
DictionaryVariables
280
0
1
1
0
DICTIONARY
5
68
100
AcDbDictionary
281
1
3
ColorSettings/BackgroundColor
350
6B
3
ColorSettings/ColorMode
350
6C
3
Grid/DisplayGrid00
350
6D
3
Grid/DisplayGrid01
350
6E
3
Grid/DisplayGrid02
350
6F
3
Grid/DisplayGrid03
350
70
3
Grid/GridSpacingX00
350
71
3
Grid/GridSpacingX01
350
72
3
Grid/GridSpacingX02
350
73
3
Grid/GridSpacingX03
350
74
3
Grid/GridSpacingY00
350
75
3
Grid/GridSpacingY01
350
76
3
Grid/GridSpacingY02
350
77
3
Grid/GridSpacingY03
350
78
3
Grid/IsometricGrid00
350
79
3
Grid/IsometricGrid01
350
7A
3
Grid/IsometricGrid02
350
7B
3
Grid/IsometricGrid03
350
7C
3
Grid/IsometricProjection00
350
7D
3
Grid/IsometricProjection01
350
7E
3
Grid/IsometricProjection02
350
7F
3
Grid/IsometricProjection03
350
80
3
Grid/MetaGridSpacingX00
350
81
3
Grid/MetaGridSpacingX01
350
82
3
Grid/MetaGridSpacingX02
350
83
3
Grid/MetaGridSpacingX03
350
84
3
Grid/MetaGridSpacingY00
350
85
3
Grid/MetaGridSpacingY01
350
86
3
Grid/MetaGridSpacingY02
350
87
3
Grid/MetaGridSpacingY03
350
88
3
MultiPageSettings/Columns
350
89
3
MultiPageSettings/GlueMarginsBottom
350
8A
3
MultiPageSettings/GlueMarginsLeft
350
8B
3
MultiPageSettings/GlueMarginsRight
350
8C
3
MultiPageSettings/GlueMarginsTop
350
8D
3
MultiPageSettings/PrintCropMarks
350
8E
3
MultiPageSettings/Rows
350
8F
3
PageSettings/OffsetX
350
90
3
PageSettings/OffsetY
350
91
3
PageSettings/PageOrientation
350
92
3
PageSettings/PaperHeight
350
93
3
PageSettings/PaperWidth
350
94
3
PageSettings/Scale
350
95
3
PageSettings/ShowPaperBorders
350
96
3
QCADVersion
350
97
3
UnitSettings/PaperUnit
350
98
3
ViewportCenter
350
99
3
ViewportHeight
350
9A
3
ViewportWidth
350
9B
0
XRECORD
5
6B
330
68
100
AcDbXrecord
280
1
1000
Blanc
0
XRECORD
5
6C
330
68
100
AcDbXrecord
280
1
1000
FullColor
0
XRECORD
5
6D
330
68
100
AcDbXrecord
280
1
290
1
0
XRECORD
5
6E
330
68
100
AcDbXrecord
280
1
290
1
0
XRECORD
5
6F
330
68
100
AcDbXrecord
280
1
290
1
0
XRECORD
5
70
330
68
100
AcDbXrecord
280
1
290
1
0
XRECORD
5
71
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
72
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
73
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
74
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
75
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
76
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
77
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
78
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
79
330
68
100
AcDbXrecord
280
1
290
0
0
XRECORD
5
7A
330
68
100
AcDbXrecord
280
1
290
0
0
XRECORD
5
7B
330
68
100
AcDbXrecord
280
1
290
0
0
XRECORD
5
7C
330
68
100
AcDbXrecord
280
1
290
0
0
XRECORD
5
7D
330
68
100
AcDbXrecord
280
1
90
65537
0
XRECORD
5
7E
330
68
100
AcDbXrecord
280
1
90
65537
0
XRECORD
5
7F
330
68
100
AcDbXrecord
280
1
90
65537
0
XRECORD
5
80
330
68
100
AcDbXrecord
280
1
90
65537
0
XRECORD
5
81
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
82
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
83
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
84
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
85
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
86
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
87
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
88
330
68
100
AcDbXrecord
280
1
1000
auto
0
XRECORD
5
89
330
68
100
AcDbXrecord
280
1
90
1
0
XRECORD
5
8A
330
68
100
AcDbXrecord
280
1
40
10.0
0
XRECORD
5
8B
330
68
100
AcDbXrecord
280
1
40
10.0
0
XRECORD
5
8C
330
68
100
AcDbXrecord
280
1
40
10.0
0
XRECORD
5
8D
330
68
100
AcDbXrecord
280
1
40
10.0
0
XRECORD
5
8E
330
68
100
AcDbXrecord
280
1
290
0
0
XRECORD
5
8F
330
68
100
AcDbXrecord
280
1
90
1
0
XRECORD
5
90
330
68
100
AcDbXrecord
280
1
40
0.0
0
XRECORD
5
91
330
68
100
AcDbXrecord
280
1
40
0.0
0
XRECORD
5
92
330
68
100
AcDbXrecord
280
1
1000
Portrait
0
XRECORD
5
93
330
68
100
AcDbXrecord
280
1
40
297.0
0
XRECORD
5
94
330
68
100
AcDbXrecord
280
1
40
210.0
0
XRECORD
5
95
330
68
100
AcDbXrecord
280
1
1000
1:1
0
XRECORD
5
96
330
68
100
AcDbXrecord
280
1
290
1
0
XRECORD
5
97
330
68
100
AcDbXrecord
280
1
1000
3.21.2.2
0
XRECORD
5
98
330
68
100
AcDbXrecord
280
1
90
4
0
XRECORD
5
9A
330
68
100
AcDbXrecord
280
1
40
64.8349902586295457
0
XRECORD
5
9B
330
68
100
AcDbXrecord
280
1
40
124.259422631461149
0
ENDSEC
0
EOF
####################################################################################################
from pathlib import Path
from Patro.Common.Logging import Logging
Logging.setup_logging()
from Patro.FileFormat.Dxf.Importer import DxfImporter
from Patro.GeometryEngine.Conic import Circle2D, Ellipse2D
from Patro.GeometryEngine.Segment import Segment2D
from Patro.GeometryEngine.Spline import BSpline2D
from Patro.GeometryEngine.Vector import Vector2D
from Patro.GraphicEngine.GraphicScene.GraphicItem import GraphicPathStyle, GraphicBezierStyle
from Patro.GraphicEngine.Painter.QtPainter import QtScene
from Patro.GraphicStyle import Colors, StrokeStyle
####################################################################################################
def spline_from_svg(scene_importer):
# m 74.999689,150.7821
# c
# 9,-10 14.500002,-5 18.916662,-0.83334 4.41667,4.16667 7.749999,7.5 11.083339,5.83334
# 3.33333,-1.66667 6.66666,-8.33334 13.33333,-11.66667 6.66667,-3.33333 16.66667,-3.33333
# 16.66667,-3.33333
# Vector2D[40. 50.]
# Vector2D[49. 60.]
# Vector2D[54.500002 55. ]
# Vector2D[58.916662 50.83334 ]
# Vector2D[63.333332 46.66667 ]
# Vector2D[66.666661 43.33334 ]
# Vector2D[70.000001 45. ]
# Vector2D[73.333331 46.66667 ]
# Vector2D[76.666661 53.33334 ]
# Vector2D[83.333331 56.66667 ]
# Vector2D[90.000001 60. ]
# Vector2D[100.000001 60. ]
# Vector2D[100.000001 60. ]
# CubicBezier2D(Vector2D[40. 50.], Vector2D[49. 60.], Vector2D[54.5 55. ], Vector2D[58.91666667 50.83333333])
# CubicBezier2D(Vector2D[58.91666667 50.83333333], Vector2D[63.33333333 46.66666667], Vector2D[66.66666667 43.33333333], Vector2D[70. 45.])
# CubicBezier2D(Vector2D[70. 45.], Vector2D[73.33333333 46.66666667], Vector2D[76.66666667 53.33333333], Vector2D[83.33333333 56.66666667])
# CubicBezier2D(Vector2D[83.33333333 56.66666667], Vector2D[90. 60.], Vector2D[100. 60.], Vector2D[100. 60.])
x0, y0 = 40, 50
control_points = (
(9, -10),
(14.500002, -5),
(18.916662, -0.83334),
(4.41667, 4.16667),
(7.749999, 7.5),
(11.083339, 5.83334),
(3.33333, -1.66667),
(6.66666, -8.33334),
(13.33333, -11.66667),
(6.66667, -3.33333),
(16.66667, -3.33333),
(16.66667, -3.33333),
)
vertices = []
point = Vector2D(x0, y0)
vertices.append(point)
for i, xy in enumerate(control_points):
xi, yi = xy
yi = -yi
if (i+1) % 3:
x = xi + x0
y = yi + y0
else:
x0 += xi
y0 += yi
x, y = x0, y0
point = Vector2D(x, y)
vertices.append(point)
path_style = GraphicBezierStyle(
line_width=3.0,
stroke_color=Colors.blue,
stroke_style=StrokeStyle.SolidLine,
show_control=True,
control_color=Colors.red,
)
for vertex in vertices:
print(vertex)
# scene_importer.scene.bezier_path(vertices, degree=3, path_style=path_style, user_data=None)
####################################################################################################
class SceneImporter:
##############################################
def __init__(self, dxf_path):
self._importer = DxfImporter(dxf_path)
self._scene = QtScene()
self._bounding_box = None
for item in self._importer:
self._add_item(item)
self._scene.bounding_box = self._bounding_box # Fixme:
##############################################
@property
def scene(self):
return self._scene
##############################################
def _update_bounding_box(self, item):
if hasattr(item, 'bounding_box'):
interval = item.bounding_box
if self._bounding_box is None:
self._bounding_box = interval
else:
self._bounding_box |= interval
##############################################
def _add_item(self, item):
# Fixme:
path_style = GraphicPathStyle(
line_width=2.0,
stroke_color=Colors.black,
stroke_style=StrokeStyle.SolidLine,
)
if isinstance(item, Segment2D):
self._scene.segment(item.p0, item.p1,
path_style,
user_data=item,
)
elif isinstance(item, Circle2D):
kwargs = dict(user_data=item)
if item.domain:
kwargs['start_angle'] = item.domain.start
kwargs['stop_angle'] = item.domain.stop
self._scene.circle(item.center, item.radius,
path_style,
**kwargs,
)
elif isinstance(item, BSpline2D):
path_style = GraphicPathStyle(
line_width=3.,
stroke_color=Colors.green,
) # Fixme
self._scene.polyline(item.points,
path_style,
user_data=item,
)
path_style = GraphicBezierStyle(
line_width=5.0,
stroke_color=Colors.black,
show_control=True,
control_color=Colors.red,
) # Fixme
for bezier in item.to_bezier():
self._scene.cubic_bezier(*bezier.points,
path_style,
user_data=item,
)
elif isinstance(item, Ellipse2D):
self._scene.ellipse(item.center,
item.x_radius,
item.y_radius,
item.angle,
path_style,
user_data=item,
)
elif isinstance(item, list):
for segment in item:
self._add_item(segment)
self._update_bounding_box(item)
####################################################################################################
# filename = 'protection-rectangulaire-v2.dxf'
filename = 'test-dxf-r15.dxf'
try:
dxf_path = Path(__file__).parent.joinpath(filename)
except:
dxf_path = Path('examples', 'dxf', filename)
scene_importer = SceneImporter(dxf_path)
# spline_from_svg(scene_importer)
application.qml_application.scene = scene_importer.scene
####################################################################################################
#
# Patro - A Python library to make patterns for fashion design
# Copyright (C) 2017 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################
####################################################################################################
from Patro.GeometryEngine.Spline import BSpline2D
from Patro.GeometryEngine.Vector import Vector2D
import numpy as np
import matplotlib.pyplot as plt
####################################################################################################
def plot_spline(spline, control=True, deboor=True, naive=False, offset=0):
# for k in range(spline.order):
# for i in range(spline.degree-k, spline.order):
# print(i, k)
# axes.plot(ts, [spline.basis_function(i, k, t) for t in ts])
offset = np.array((0, offset))
if control:
control_point_array = spline.point_array + offset
axes.plot(control_point_array[:,0], control_point_array[:,1])
if naive:
knots = spline.knots
print(knots)
# for t_inf in spline.knot_iter:
# ts = np.linspace(t_inf, t_inf +1, 30)
for i in range(len(spline.knots) -1):
t_inf, t_sup = spline.knots[i], spline.knots[i+1]
if t_sup == spline.end_knot:
t_sup -= 1e-6
ts = np.linspace(t_inf, t_sup, 30)
if t_inf < t_sup:
curve_points = np.zeros((len(ts), 2))
for i, t in enumerate(ts):
p = spline.point_at_t(t, naive=True)
curve_points[i] = p
curve_points += offset
axes.plot(curve_points[:,0], curve_points[:,1])
if deboor:
end_knot = spline.end_knot
if not spline.uniform:
end_knot -= 1e-6
print('end knot', spline.uniform, end_knot)
ts = np.linspace(0, end_knot, 50)
curve_points = np.zeros((len(ts), 2))
for i, t in enumerate(ts):
p = spline.point_at_t(t)
curve_points[i] = p
curve_points += offset
axes.plot(curve_points[:,0], curve_points[:,1], 'o')
####################################################################################################
# degree = 3
# order = degree +1
# for number_of_points in range(order, order + 5):
# print(BSpline2D.uniform_knots(degree, number_of_points))
# points = (
# Vector2D(1, 1),
# Vector2D(2, 2),
# Vector2D(3, 2),
# Vector2D(4, 1),
# )
# degree = 3
# spline = BSpline2D(points, degree)
# plot_spline(spline)
points = (
Vector2D(0, 0),
Vector2D(5, 5),
Vector2D(10, -5),
Vector2D(15, 5),
Vector2D(20, -5),
Vector2D(25, 5),
)
degree = 3
spline = BSpline2D(points, degree)
# spline2 = spline
# spline2 = spline2.insert_knot(1.5)
# spline2 = spline2.insert_knot(2.5)
spline2 = spline.to_bezier_form()
bezier_curves = spline.to_bezier()
print(bezier_curves)
figure, axes = plt.subplots()
axes.grid(True)
plot_spline(spline, deboor=True, naive=True, offset=-.1)
plot_spline(spline2, deboor=True, naive=True, offset=.1)
plt.show()
####################################################################################################
from Patro.Common.Logging import Logging
Logging.setup_logging()
from Patro.GeometryEngine.Path import (
Path2D,
LinearSegment, QuadraticBezierSegment, CubicBezierSegment
)
from Patro.GeometryEngine.Vector import Vector2D
from Patro.GraphicEngine.GraphicScene.GraphicItem import GraphicPathStyle, GraphicBezierStyle
from Patro.GraphicEngine.Painter.QtPainter import QtScene
from Patro.GraphicStyle import Colors, StrokeStyle
####################################################################################################
class SceneBuilder:
##############################################
def __init__(self):
self._scene = QtScene()
self._bounding_box = None
for path in (
self._make_path1(),
self._make_path2(),
self._make_path3(),
self._make_path4(),
):
self._add_path(path)
self._scene.bounding_box = self._bounding_box # Fixme:
##############################################
@property
def scene(self):
return self._scene
##############################################
def _update_bounding_box(self, item):
interval = item.bounding_box
if self._bounding_box is None:
self._bounding_box = interval
else:
self._bounding_box |= interval
##############################################
def _make_path1(self):
start_point = Vector2D(0, 0)
path = Path2D(start_point)
path.horizontal_to(10)
path.vertical_to(10)
path.north_east_to(10)
path.north_west_to(10)
path.south_west_to(10)
path.south_east_to(5)
path.south_to(5)
path.west_to(10)
path.north_to(5)
path.east_to(5)
return path
##############################################
def _make_path2(self):
start_point = Vector2D(20, 0)
path = Path2D(start_point)
path.horizontal_to(10)
path.vertical_to(10)
path.north_east_to(10)
path.north_west_to(10)
path.south_west_to(10)
path.south_east_to(5)
return path
##############################################
def _make_path3(self):
start_point = Vector2D(40, 0)
path = Path2D(start_point)
path.line_to(Vector2D(10, 0))
path.line_to(Vector2D(0, 10), radius=5)
path.line_to(Vector2D(10, 0), radius=5)
path.line_to(Vector2D(0, 20), radius=5)
path.line_to(Vector2D(-10, 0), radius=5)
path.line_to(Vector2D(0, -10), radius=5)
path.close(radius=0) # Fixme:
return path
##############################################
def _make_path4(self):
start_point = Vector2D(70, 0)
path = Path2D(start_point)
# path.line_to(Vector2D(10, 0))
# path.line_to(Vector2D(0, 10), radius=5)
# path.line_to(Vector2D(-10, 0), radius=5)
path.east_to(10)
path.north_to(10, radius=5)
path.west_to(10, radius=5)
return path
##############################################
def _add_path(self, path):
path_style = GraphicPathStyle(
line_width=3.0,
stroke_color=Colors.black,
stroke_style=StrokeStyle.SolidLine,
)
for item in path:
# print('Path part:', item)
if isinstance(item, LinearSegment):
# print('linear', item.start_point, item.stop_point, item.points)
if item.radius is not None:
print('-'*10)
print(item.bissector)
print(item.bulge_angle, item.bulge_center, item.start_point, item.stop_point)
print(item.bulge_geometry)
arc = item.bulge_geometry
self._scene.circle(arc.center, arc.radius,
path_style,
start_angle=arc.domain.start,
stop_angle=arc.domain.stop,
user_data=item,
)
self._scene.segment(*item.points,
path_style,
user_data=item,
)
elif isinstance(item, QuadraticBezierSegment):
self._scene.quadratic_bezier(*item.points,
path_style,
user_data=item,
)
elif isinstance(item, CubicBezierSegment):
self._scene.cubic_bezier(*item.points,
path_style,
user_data=item,
)
# Fixme: why here ???
self._update_bounding_box(item)
####################################################################################################
scene = QtScene()
scene_builder = SceneBuilder()
application.qml_application.scene = scene_builder.scene
<?xml version="1.0" encoding="UTF-8"?>
<pattern>
<!--Pattern created with Valentina v0.6.0.912b (https://valentinaproject.bitbucket.io/).-->
<version>0.7.10</version>
<unit>cm</unit>
<description/>
<notes/>
<measurements/>
<increments/>
<previewCalculations/>
<draw name="Pattern piece 1">
<calculation>
<point id="1" mx="0.132292" my="0.264583" name="A" showLabel="true" type="single" x="0.79375" y="1.05833"/>
<point angle="0" basePoint="1" id="2" length="10" lineColor="black" mx="0.132292" my="0.264583" name="A1" showLabel="true" type="endLine" typeLine="hair"/>
<point angle="270" basePoint="2" id="3" length="10&#10;" lineColor="black" mx="0.132292" my="0.264583" name="A2" showLabel="true" type="endLine" typeLine="hair"/>
<point firstPoint="1" id="4" mx="0.132292" my="0.264583" name="A3" secondPoint="3" showLabel="true" type="pointOfIntersection"/>
<line firstPoint="3" id="5" lineColor="black" secondPoint="4" typeLine="hair"/>
<line firstPoint="4" id="6" lineColor="black" secondPoint="1" typeLine="hair"/>
</calculation>
<modeling>
<point id="13" idObject="1" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="14" idObject="2" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="15" idObject="3" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="16" idObject="4" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="22" idObject="1" inUse="true" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="23" idObject="2" inUse="true" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="24" idObject="4" inUse="true" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
</modeling>
<details>
<detail forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="17" inLayout="true" mx="0" my="0" name="Detail 1" seamAllowance="false" united="false" version="2" width="1">
<data annotation="" foldPosition="" fontSize="0" height="1" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="1"/>
<patternInfo fontSize="0" height="1" mx="0" my="0" rotation="0" visible="false" width="1"/>
<grainline arrows="0" length="1" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="13" type="NodePoint"/>
<node idObject="14" type="NodePoint"/>
<node idObject="15" type="NodePoint"/>
<node idObject="16" type="NodePoint"/>
</nodes>
</detail>
<detail forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="25" inLayout="true" mx="0" my="0" name="Detail 11" seamAllowance="false" united="false" version="2" width="1">
<data annotation="" foldPosition="" fontSize="0" height="1" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="1"/>
<patternInfo fontSize="0" height="1" mx="0" my="0" rotation="0" visible="false" width="1"/>
<grainline arrows="0" length="1" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="22" type="NodePoint"/>
<node idObject="23" type="NodePoint"/>
<node idObject="24" type="NodePoint"/>
</nodes>
</detail>
</details>
<groups/>
</draw>
<draw name="Pattern piece 2">
<calculation>
<point id="7" mx="0.132292" my="0.264583" name="B" showLabel="true" type="single" x="13.6961" y="1.05833"/>
<point angle="0" basePoint="7" id="8" length="5" lineColor="black" mx="0.132292" my="0.264583" name="B1" showLabel="true" type="endLine" typeLine="hair"/>
<point firstPoint="7" id="9" length="CurrentLength/2" lineColor="black" mx="0.132292" my="0.264583" name="B2" secondPoint="8" showLabel="true" type="alongLine" typeLine="none"/>
<point angle="0" firstPoint="9" id="10" length="-5&#10;" lineColor="black" mx="0.132292" my="0.264583" name="B3" secondPoint="8" showLabel="true" type="normal" typeLine="hair"/>
<line firstPoint="7" id="11" lineColor="black" secondPoint="10" typeLine="hair"/>
<line firstPoint="10" id="12" lineColor="black" secondPoint="8" typeLine="hair"/>
</calculation>
<modeling>
<point id="18" idObject="7" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="19" idObject="8" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
<point id="20" idObject="10" inUse="false" mx="0.132292" my="0.264583" showLabel="true" type="modeling"/>
</modeling>
<details>
<detail forbidFlipping="false" forceFlipping="false" hideMainPath="false" id="21" inLayout="true" mx="0" my="-0.0264583" name="Detail 2" seamAllowance="false" united="false" version="2" width="1">
<data annotation="" foldPosition="" fontSize="0" height="1" letter="" mx="0" my="0" onFold="false" orientation="" quantity="1" rotation="0" rotationWay="" tilt="" visible="false" width="1"/>
<patternInfo fontSize="0" height="1" mx="0" my="0" rotation="0" visible="false" width="1"/>
<grainline arrows="0" length="1" mx="0" my="0" rotation="90" visible="false"/>
<nodes>
<node idObject="18" type="NodePoint"/>
<node idObject="19" type="NodePoint"/>
<node idObject="20" type="NodePoint"/>
</nodes>
</detail>
</details>
<groups/>
</draw>
</pattern>
......@@ -15,7 +15,11 @@ from Patro.GraphicEngine.Painter.TexPainter import TexPainter
####################################################################################################
val_file = ValFile(Path('patterns', 'flat-city-trouser.val'))
try:
val_path = Path(__file__).parent.joinpath('patterns', 'flat-city-trouser.val')
except:
val_path = Path('examples', 'patterns', 'flat-city-trouser.val')
val_file = ValFile(val_path)
pattern = val_file.pattern
pattern.dump()
......@@ -32,8 +36,6 @@ output.mkdir(exist_ok=True)
val_file.write(output.joinpath('write-test.val'))
scene = pattern.detail_scene()
# tex_path = output.joinpath('pattern-a0.tex')
# paper = PaperSize('a0', 'portrait', 10)
# tex_painter = TexPainter(str(tex_path), scene, paper)
......@@ -58,6 +60,6 @@ scene = pattern.detail_scene()
# svg_path = output.joinpath('pattern-a0.svg')
# svg_painter = SvgPainter(svg_path, scene, paper)
paper = PaperSize('a0', 'portrait', 10)
dxf_path = output.joinpath('pattern.dxf')
dxf_painter = DxfPainter(dxf_path, scene, paper)
# paper = PaperSize('a0', 'portrait', 10)
# dxf_path = output.joinpath('pattern.dxf')
# dxf_painter = DxfPainter(dxf_path, scene, paper)
####################################################################################################
from pathlib import Path
from Patro.Common.Logging import Logging
Logging.setup_logging()
from Patro.FileFormat.Valentina.Pattern import ValFile
from Patro.GraphicEngine.Painter.Paper import PaperSize
from Patro.GraphicEngine.Painter.QtPainter import QtScene
####################################################################################################
# val_file = 'flat-city-trouser.val'
val_file = 'path-bezier.val'
try:
val_path = Path(__file__).parent.joinpath('patterns', val_file)
except:
val_path = Path('examples', 'patterns', val_file)
val_file = ValFile(val_path)
pattern = val_file.pattern
kwargs = dict(scene_cls=QtScene)
first_scope = pattern.scope(0)
scene = first_scope.sketch.detail_scene(**kwargs)
application.qml_application.scene = scene
####################################################################################################
from pathlib import Path
from Patro.Common.Logging import Logging
Logging.setup_logging()
from Patro.FileFormat.Valentina.Pattern import ValFileReader
####################################################################################################
# val_file = 'several-pieces.val'
val_file = 'flat-city-trouser.val'
parts = ('patterns', val_file)
try:
val_path = Path(__file__).parent.joinpath(*parts)
except:
val_path = Path('examples', *parts)
val_file = ValFileReader(val_path)
pattern = val_file.pattern
# pattern.dump()
# for calculation in pattern.calculations:
# print(calculation.to_python())
# nodes = pattern.calculator.dag.topological_sort()
# for node in nodes:
# print(node.data)
# output = Path('output')
# output.mkdir(exist_ok=True)
# val_file.write(output.joinpath('write-test.val'))
non-public-submodule @ aa055092
Subproject commit 5327151f61f1c57144eb8f118bae275c55b9e247
Subproject commit aa0550928dda27d42b6951b75366866595b54caf
source /opt/python-virtual-env/py36/bin/activate
source /opt/python-virtual-env/py37/bin/activate
append_to_python_path_if_not ${PWD}
append_to_python_path_if_not ${PWD}/tools
if [ -e ${PWD}/non-public-submodule/setenv.sh ]; then
source ${PWD}/non-public-submodule/setenv.sh
fi
......@@ -73,6 +73,41 @@ class TestCubicBezier(unittest.TestCase):
####################################################################################################
class TestCubicSpline(unittest.TestCase):
##############################################
def test_spline_part(self):
p0 = Vector2D(0, 0)
p1 = Vector2D(3, 5)
p2 = Vector2D(6, 5)
p3 = Vector2D(10, 0)
bezier = CubicBezier2D(p0, p1, p2, p3)
spline = bezier.to_spline()
bezier2 = spline.to_bezier()
self.assertTrue(bezier2.is_close(bezier))
##############################################
def test_spline(self):
points = (
Vector2D(0, 0),
Vector2D(3, 5),
Vector2D(6, 6),
Vector2D(10, 8),
Vector2D(15, 10),
Vector2D(19, 15),
)
spline = CubicSpline2D(points)
for part in spline.iter_on_parts():
print(part)
####################################################################################################
if __name__ == '__main__':
unittest.main()