mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-05 11:30:06 +01:00
4 August 2016 Phoenix updates for wx.lib.pdfviewer and demo/PDFViewer
demo/viewer.py and viewer_basics.py removed - was demo of obsolete vtk
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
import wx
|
||||
|
||||
try:
|
||||
import pyPdf
|
||||
from wx.lib.pdfviewer import pdfViewer, pdfButtonPanel
|
||||
havePyPdf = True
|
||||
except ImportError:
|
||||
@@ -51,10 +50,13 @@ def runTest(frame, nb, log):
|
||||
win = TestPanel(nb, log)
|
||||
return win
|
||||
else:
|
||||
from Main import MessagePanel
|
||||
from wx.lib.msgpanel import MessagePanel
|
||||
win = MessagePanel(nb,
|
||||
'This demo requires the pyPdf package to be installed.\n'
|
||||
'See: http://pybrary.net/pyPdf/',
|
||||
'This demo requires either the\n'
|
||||
'PyMuPDF see http://pythonhosted.org/PyMuPDF\n'
|
||||
'or\n'
|
||||
'PyPDF2 see http://pythonhosted.org/PyPDF2\n'
|
||||
'package installed.\n',
|
||||
'Sorry', wx.ICON_WARNING)
|
||||
return win
|
||||
|
||||
@@ -66,9 +68,22 @@ The wx.lib.pdfviewer.pdfViewer class is derived from wx.ScrolledWindow
|
||||
and can display and print PDF files. The whole file can be scrolled from
|
||||
end to end at whatever magnification (zoom-level) is specified.
|
||||
|
||||
<p> The viewer uses <b>pyPdf</b> to parse the pdf file so it is a requirement that
|
||||
this must be installed. The pyPdf home page is http://pybrary.net/pyPdf/
|
||||
and the library can also be downloaded from http://pypi.python.org/pypi/pyPdf/1.12
|
||||
<p> The viewer checks for the <b>PyMuPDF</b> then the <b>PyPDF2</b> package.
|
||||
If neither are installed an import error exception will be raised.
|
||||
|
||||
<p>PyMuPDF contains the Python bindings for the underlying MuPDF library, a cross platform,
|
||||
complete PDF rendering library that is GPL licenced. PyMuPDF version 1.9.2 or later is required.
|
||||
|
||||
<p>Further details on PyMuPDF can be found via http://pythonhosted.org/PyMuPDF
|
||||
|
||||
<p>PyPDF2 provides a PdfFileReader class that is used to read the content stream of a PDF
|
||||
file which is subsequently rendered by the viewer itself.
|
||||
Please note that this is not a complete implementation of the pdf specification and
|
||||
will probably fail to render any random PDF file you supply. However it does seem to
|
||||
behave correctly with files that have been produced by ReportLab using Western languages.
|
||||
The main limitation is that it doesn't currently support embedded fonts.
|
||||
|
||||
<p>Additional details on PyPDF2 can be found via http://pythonhosted.org/PyPDF2
|
||||
|
||||
<p> There is an optional pdfButtonPanel class, derived from wx.lib.agw.buttonpanel,
|
||||
that can be placed, for example, at the top of the scrolled viewer window,
|
||||
@@ -82,12 +97,6 @@ Externally callable methods are: LoadFile, Save, Print, SetZoom, and GoPage.
|
||||
otherwise wx.GraphicsContext is used. Printing is achieved by writing
|
||||
directly to a wx.PrintDC and using wx.Printer.
|
||||
|
||||
<p> Please note that pdfviewer is a far from complete implementation of the pdf
|
||||
specification and will probably fail to display any random file you supply.
|
||||
However it does seem to be OK with the sort of files produced by ReportLab that
|
||||
use Western languages. The biggest limitation is probably that it doesn't (yet?)
|
||||
support embedded fonts and will substitute one of the standard fonts instead.
|
||||
|
||||
</body></html>
|
||||
"""
|
||||
|
||||
|
||||
100
demo/viewer.py
100
demo/viewer.py
@@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Run wxPython in a second thread.
|
||||
|
||||
Overview:
|
||||
Importing this module creates a second thread and starts
|
||||
wxPython in that thread. Its single method,
|
||||
add_cone(), sends an event to the second thread
|
||||
telling it to create a VTK viewer window with a cone in
|
||||
it.
|
||||
|
||||
This module is meant to be imported into the standard
|
||||
Python interpreter. It also works with Pythonwin.
|
||||
It doesn't seem to work with IDLE (on NT anyways).
|
||||
It should also work in a wxPython application.
|
||||
|
||||
Applications already running a wxPython app do not
|
||||
need to start a second thread. In these cases,
|
||||
viewer creates the cone windows in the current
|
||||
thread. You can test this by running shell.py
|
||||
that comes with wxPython, importing viewer and
|
||||
calling add_cone.
|
||||
|
||||
Usage:
|
||||
[user]$ python
|
||||
Python 1.5.2 (#1, Sep 17 1999, 20:15:36) ...
|
||||
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
|
||||
>>> import viewer
|
||||
>>> viewer.add_cone() # pop up a cone window
|
||||
>>> a = 1
|
||||
1
|
||||
>>> viewer.add_cone() # create another cone window
|
||||
|
||||
Why would anyone do this?:
|
||||
When using wxPython, the call to app.Mainloop() takes over
|
||||
the thread from which it is called. This presents a
|
||||
problem for applications that want to use the standard
|
||||
Python command line user interface, while occasionally
|
||||
creating a GUI window for viewing an image, plot, etc.
|
||||
One solution is to manage the GUI in a second thread.
|
||||
|
||||
wxPython does not behave well if windows are created in
|
||||
a thread other than the one where wxPython was originally
|
||||
imported. ( I assume importing wxPython initializes some
|
||||
info in the thread). The current solution is to make the
|
||||
original import of wxPython in the second thread and then
|
||||
create all windows in that second thread.
|
||||
|
||||
Methods in the main thread can create a new window by issuing
|
||||
events to a "catcher" window in the second thread. This
|
||||
catcher window has event handlers that actually create the
|
||||
new window.
|
||||
"""
|
||||
|
||||
class viewer_thread:
|
||||
def start(self):
|
||||
""" start the GUI thread
|
||||
"""
|
||||
import time
|
||||
import thread
|
||||
thread.start_new_thread(self.run, ())
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Note that viewer_basices is first imported ***here***.
|
||||
This is the second thread. viewer_basics imports
|
||||
wxPython. if we imported it at
|
||||
the module level instead of in this function,
|
||||
the import would occur in the main thread and
|
||||
wxPython wouldn't run correctly in the second thread.
|
||||
"""
|
||||
import viewer_basics
|
||||
|
||||
try:
|
||||
self.app = viewer_basics.SecondThreadApp(0)
|
||||
self.app.MainLoop()
|
||||
except TypeError:
|
||||
self.app = None
|
||||
|
||||
def add_cone(self):
|
||||
"""
|
||||
send an event to the catcher window in the
|
||||
other thread and tell it to create a cone window.
|
||||
"""
|
||||
import viewer_basics
|
||||
|
||||
if self.app:
|
||||
evt = viewer_basics.AddCone()
|
||||
viewer_basics.wxPostEvent(self.app.catcher, evt)
|
||||
else:
|
||||
viewer_basics.add_cone()
|
||||
|
||||
viewer = viewer_thread()
|
||||
viewer.start()
|
||||
|
||||
def add_cone():
|
||||
viewer.add_cone()
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# 11/15/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
||||
#
|
||||
# o Updated for wx namespace
|
||||
# o No idea what this does.
|
||||
#
|
||||
|
||||
import wx
|
||||
import wx.lib.vtk as vtk
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
class VtkFrame(wx.Frame):
|
||||
"""
|
||||
Simple example VTK window that contains a cone.
|
||||
"""
|
||||
def __init__(self, parent, id, title):
|
||||
wx.Frame.__init__(self, parent, id, title, size=(450, 300))
|
||||
win = vtk.VTKRenderWindow(self, -1)
|
||||
|
||||
renWin = win.GetRenderWindow()
|
||||
|
||||
ren = vtk.vtkRenderer()
|
||||
renWin.AddRenderer(ren)
|
||||
cone = vtk.vtkConeSource()
|
||||
coneMapper = vtk.vtkPolyDataMapper()
|
||||
coneMapper.SetInput(cone.GetOutput())
|
||||
coneActor = vtk.vtkActor()
|
||||
coneActor.SetMapper(coneMapper)
|
||||
ren.AddActor(coneActor)
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Using new event binder
|
||||
wx_EVT_ADD_CONE = wx.NewEventType()
|
||||
EVT_ADD_CONE = wx.PyEventBinder(wx_EVT_ADD_CONE, 1)
|
||||
|
||||
class AddCone(wx.PyEvent):
|
||||
def __init__(self):
|
||||
wx.PyEvent.__init__(self)
|
||||
self.SetEventType(wx_EVT_ADD_CONE)
|
||||
|
||||
|
||||
class HiddenCatcher(wx.Frame):
|
||||
"""
|
||||
The "catcher" frame in the second thread.
|
||||
It is invisible. It's only job is to receive
|
||||
Events from the main thread, and create
|
||||
the appropriate windows.
|
||||
"""
|
||||
def __init__(self):
|
||||
wx.Frame.__init__(self, None, -1, '')
|
||||
self.Bind(EVT_ADD_CONE, self.AddCone)
|
||||
|
||||
def AddCone(self,evt):
|
||||
add_cone()
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class SecondThreadApp(wx.App):
|
||||
"""
|
||||
wxApp that lives in the second thread.
|
||||
"""
|
||||
def OnInit(self):
|
||||
catcher = HiddenCatcher()
|
||||
#self.SetTopWindow(catcher)
|
||||
self.catcher = catcher
|
||||
return True
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def add_cone():
|
||||
frame = VtkFrame(None, -1, "Cone")
|
||||
frame.Show(True)
|
||||
|
||||
@@ -23,18 +23,22 @@ The :class:`~lib.pdfviewer.viewer.pdfViewer` class is derived from :class:`Scro
|
||||
and can display and print PDF files. The whole file can be scrolled from
|
||||
end to end at whatever magnification (zoom-level) is specified.
|
||||
|
||||
The viewer uses pyPDF2 or pyPdf, if neither of them are installed an
|
||||
import error exception will be thrown.
|
||||
The viewer uses PyMuPDF (version 1.9.2 or later) or PyPDF2.
|
||||
If neither of them are installed an import error exception will be raised.
|
||||
|
||||
Additional details on pyPdf can be found:
|
||||
PyMuPDF contains the Python bindings for the underlying MuPDF library, a cross platform,
|
||||
complete PDF rendering library that is GPL licenced.
|
||||
|
||||
- home page: http://pybrary.net/pyPdf/
|
||||
- download: https://pypi.python.org/pypi/pyPdf
|
||||
Further details on PyMuPDF can be found via http://pythonhosted.org/PyMuPDF
|
||||
|
||||
Additional details on pyPDF2 can be found:
|
||||
PyPDF2 provides a PdfFileReader class that is used to read the content stream of a PDF
|
||||
file which is subsequently rendered by :class:`~lib.pdfviewer.viewer.pdfViewer` itself.
|
||||
Please note that this is not a complete implementation of the pdf specification and
|
||||
will probably fail to display any random file you supply. However it does seem to
|
||||
satisfactorily render files typically produced by ReportLab using Western languages.
|
||||
The main limitation is that it doesn't currently support embedded fonts.
|
||||
|
||||
- home page: http://knowah.github.com/PyPDF2/
|
||||
- download: https://github.com/knowah/PyPDF2/
|
||||
Additional details on PyPDF2 can be found via http://pythonhosted.org/PyPDF2
|
||||
|
||||
There is an optional :class:`~lib.pdfviewer.buttonpanel.pdfButtonPanel` class, derived from
|
||||
:class:`~lib.agw.buttonpanel`, that can be placed, for example, at the top of the
|
||||
@@ -102,22 +106,10 @@ The viewer renders the pdf file content using Cairo if installed,
|
||||
otherwise :class:`GraphicsContext` is used. Printing is achieved by writing
|
||||
directly to a :class:`PrinterDC` and using :class:`Printer`.
|
||||
|
||||
Please note that :class:`~lib.pdfviewer.viewer.pdfViewer` is a far from complete
|
||||
implementation of the pdf specification and will probably fail to display any
|
||||
random file you supply. However it does seem to be OK with the sort of files
|
||||
produced by ReportLab that use Western languages. The biggest limitation is
|
||||
probably that it doesn't (yet?) support embedded fonts and will substitute one
|
||||
of the standard fonts instead.
|
||||
|
||||
The icons used in :class:`~lib.pdfviewer.buttonpanel.pdfButtonPanel` are Free Icons
|
||||
by Axialis Software: http://www.axialis.com
|
||||
|
||||
You can freely use them in any project or website, commercially or not.
|
||||
|
||||
TERMS OF USE:
|
||||
|
||||
You must keep the credits of the authors: "Axialis Team", even if you modify them.
|
||||
See ./bitmaps/ReadMe.txt for further details
|
||||
by Axialis Software: http://www.axialis.com. You can freely use them in any project,
|
||||
commercially or not, but you must keep the credits of the authors:
|
||||
"Axialis Team", even if you modify them. See ./bitmaps/ReadMe.txt for further details.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ def compute_points(controlpoints, nsteps=30):
|
||||
"""
|
||||
Input 4 control points as :class:`RealPoint` and convert to vec2d instances.
|
||||
compute the nsteps points on the resulting curve and return them
|
||||
as a list of :class:`wx.Point`
|
||||
as a list of :class:`Point`
|
||||
"""
|
||||
controlvectors = []
|
||||
for p in controlpoints:
|
||||
|
||||
@@ -28,24 +28,24 @@ class pdfButtonPanel(bp.ButtonPanel):
|
||||
from wx.lib.agw.buttonpanel and provides buttons to manipulate the viewed
|
||||
PDF, e.g. zoom, save, print etc.
|
||||
"""
|
||||
def __init__(self, parent, id, pos, size, style):
|
||||
def __init__(self, parent, nid, pos, size, style):
|
||||
"""
|
||||
Default class constructor.
|
||||
|
||||
:param wx.Window `parent`: parent window. Must not be ``None``;
|
||||
:param integer `id`: window identifier. A value of -1 indicates a default value;
|
||||
:param Window `parent`: parent window. Must not be ``None``;
|
||||
:param integer `nid`: window identifier. A value of -1 indicates a default value;
|
||||
:param `pos`: the control position. A value of (-1, -1) indicates a default position,
|
||||
chosen by either the windowing system or wxPython, depending on platform;
|
||||
:type `pos`: tuple or :class:`wx.Point`
|
||||
:type `pos`: tuple or :class:`Point`
|
||||
:param `size`: the control size. A value of (-1, -1) indicates a default size,
|
||||
chosen by either the windowing system or wxPython, depending on platform;
|
||||
:type `size`: tuple or :class:`wx.Size`
|
||||
:type `size`: tuple or :class:`Size`
|
||||
:param integer `style`: the button style (unused);
|
||||
|
||||
"""
|
||||
self.viewer = None # reference to viewer is set by their common parent
|
||||
self.numpages = None
|
||||
bp.ButtonPanel.__init__(self, parent, id, "",
|
||||
bp.ButtonPanel.__init__(self, parent, nid, "",
|
||||
agwStyle=bp.BP_USE_GRADIENT, alignment=bp.BP_ALIGN_LEFT)
|
||||
self.SetProperties()
|
||||
self.CreateButtons()
|
||||
@@ -92,7 +92,7 @@ class pdfButtonPanel(bp.ButtonPanel):
|
||||
self.Freeze()
|
||||
for item in panelitems:
|
||||
if item[0].lower() == 'btn':
|
||||
type, image, kind, popup, handler = item
|
||||
x_type, image, kind, popup, handler = item
|
||||
btn = bp.ButtonInfo(self, wx.NewId(),image, kind=kind,
|
||||
shortHelp=popup, longHelp='')
|
||||
self.AddButton(btn)
|
||||
@@ -219,7 +219,7 @@ class pdfButtonPanel(bp.ButtonPanel):
|
||||
|
||||
def OnZoomSet(self, event):
|
||||
"""
|
||||
The zoom set handler, either a list selection of a value entered.
|
||||
The zoom set handler, either a list selection or a value entered.
|
||||
"""
|
||||
MINZ = 0
|
||||
MAXZ = 1000
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#----------------------------------------------------------------------------
|
||||
"""
|
||||
This module implements an API similar to :class:`GraphicsContext` and the
|
||||
related classes. The implementation is done using :class:`wx.DC`
|
||||
related classes. The implementation is done using :class:`DC`
|
||||
|
||||
Why do this? Neither :class:`GraphicsContext` nor the Cairo-based
|
||||
GraphicsContext API provided by wx.lib.graphics can be written
|
||||
@@ -148,9 +148,9 @@ class dcGraphicsContext(object):
|
||||
The incoming co-ordinates have a bottom left origin with increasing
|
||||
y downwards (so y values are all negative). The DC origin is top left
|
||||
also with increasing y down.
|
||||
:class:`wx.DC` and :class:`GraphicsContext` fonts are too big in the ratio
|
||||
:class:`DC` and :class:`GraphicsContext` fonts are too big in the ratio
|
||||
of pixels per inch to points per inch. If screen rendering used Cairo,
|
||||
printed fonts need to be scaled but if :class:`wx.GCDC` was used, they are
|
||||
printed fonts need to be scaled but if :class:`GCDC` was used, they are
|
||||
already scaled.
|
||||
|
||||
:param `context`: **TBW** (?)
|
||||
@@ -229,30 +229,30 @@ class dcGraphicsContext(object):
|
||||
|
||||
def SetPen(self, pen):
|
||||
"""
|
||||
Set the :class:`wx.Pen` to be used for stroking lines in future drawing
|
||||
Set the :class:`Pen` to be used for stroking lines in future drawing
|
||||
operations.
|
||||
|
||||
:param `pen`: the :class:`wx.Pen` to be used from now on.
|
||||
:param `pen`: the :class:`Pen` to be used from now on.
|
||||
|
||||
"""
|
||||
self._context.SetPen(pen)
|
||||
|
||||
def SetBrush(self, brush):
|
||||
"""
|
||||
Set the :class:`wx.Brush` to be used for filling shapes in future drawing
|
||||
Set the :class:`Brush` to be used for filling shapes in future drawing
|
||||
operations.
|
||||
|
||||
:param `brush`: the :class:`wx.Brush` to be used from now on.
|
||||
:param `brush`: the :class:`Brush` to be used from now on.
|
||||
|
||||
"""
|
||||
self._context.SetBrush(brush)
|
||||
|
||||
def SetFont(self, font, colour=None):
|
||||
"""
|
||||
Sets the :class:`wx.Font` to be used for drawing text.
|
||||
Sets the :class:`Font` to be used for drawing text.
|
||||
Don't set the dc font yet as it may need to be scaled
|
||||
|
||||
:param `font`: the :class:`wx.Font` for drawing text
|
||||
:param `font`: the :class:`Font` for drawing text
|
||||
:param `colour`: the colour to be used
|
||||
|
||||
"""
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
# History: Created 17 Jun 2009
|
||||
#
|
||||
# Tags: phoenix-port, documented, unittest
|
||||
#
|
||||
# Tags: phoenix-port, documented
|
||||
#----------------------------------------------------------------------------
|
||||
"""
|
||||
This module is used to compute Bezier curves.
|
||||
@@ -339,141 +338,15 @@ class vec2d(object):
|
||||
def cross(self, other):
|
||||
return self.x*other[1] - self.y*other[0]
|
||||
|
||||
def interpolate_to(self, other, range):
|
||||
return vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)
|
||||
def interpolate_to(self, other, arange):
|
||||
return vec2d(self.x + (other[0] - self.x)*arange, self.y + (other[1] - self.y)*arange)
|
||||
|
||||
def convert_to_basis(self, x_vector, y_vector):
|
||||
return vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())
|
||||
return vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(),
|
||||
self.dot(y_vector)/y_vector.get_length_sqrd())
|
||||
|
||||
def __getstate__(self):
|
||||
return [self.x, self.y]
|
||||
|
||||
def __setstate__(self, dict):
|
||||
self.x, self.y = dict
|
||||
|
||||
########################################################################
|
||||
## Unit Testing ##
|
||||
########################################################################
|
||||
if __name__ == "__main__":
|
||||
|
||||
import unittest
|
||||
import pickle
|
||||
|
||||
####################################################################
|
||||
class UnitTestVec2D(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def testCreationAndAccess(self):
|
||||
v = vec2d(111,222)
|
||||
self.assert_(v.x == 111 and v.y == 222)
|
||||
v.x = 333
|
||||
v[1] = 444
|
||||
self.assert_(v[0] == 333 and v[1] == 444)
|
||||
|
||||
def testMath(self):
|
||||
v = vec2d(111,222)
|
||||
self.assertEqual(v + 1, vec2d(112,223))
|
||||
self.assert_(v - 2 == [109,220])
|
||||
self.assert_(v * 3 == (333,666))
|
||||
self.assert_(v / 2.0 == vec2d(55.5, 111))
|
||||
self.assert_(v / 2 == (55, 111))
|
||||
self.assert_(v ** vec2d(2,3) == [12321, 10941048])
|
||||
self.assert_(v + [-11, 78] == vec2d(100, 300))
|
||||
self.assert_(v / [11,2] == [10,111])
|
||||
|
||||
def testReverseMath(self):
|
||||
v = vec2d(111,222)
|
||||
self.assert_(1 + v == vec2d(112,223))
|
||||
self.assert_(2 - v == [-109,-220])
|
||||
self.assert_(3 * v == (333,666))
|
||||
self.assert_([222,999] / v == [2,4])
|
||||
self.assert_([111,222] ** vec2d(2,3) == [12321, 10941048])
|
||||
self.assert_([-11, 78] + v == vec2d(100, 300))
|
||||
|
||||
def testUnary(self):
|
||||
v = vec2d(111,222)
|
||||
v = -v
|
||||
self.assert_(v == [-111,-222])
|
||||
v = abs(v)
|
||||
self.assert_(v == [111,222])
|
||||
|
||||
def testLength(self):
|
||||
v = vec2d(3,4)
|
||||
self.assert_(v.length == 5)
|
||||
self.assert_(v.get_length_sqrd() == 25)
|
||||
self.assert_(v.normalize_return_length() == 5)
|
||||
self.assert_(v.length == 1)
|
||||
v.length = 5
|
||||
self.assert_(v == vec2d(3,4))
|
||||
v2 = vec2d(10, -2)
|
||||
self.assert_(v.get_distance(v2) == (v - v2).get_length())
|
||||
|
||||
def testAngles(self):
|
||||
v = vec2d(0, 3)
|
||||
self.assertEquals(v.angle, 90)
|
||||
v2 = vec2d(v)
|
||||
v.rotate(-90)
|
||||
self.assertEqual(v.get_angle_between(v2), 90)
|
||||
v2.angle -= 90
|
||||
self.assertEqual(v.length, v2.length)
|
||||
self.assertEquals(v2.angle, 0)
|
||||
self.assertEqual(v2, [3, 0])
|
||||
self.assert_((v - v2).length < .00001)
|
||||
self.assertEqual(v.length, v2.length)
|
||||
v2.rotate(300)
|
||||
self.assertAlmostEquals(v.get_angle_between(v2), -60)
|
||||
v2.rotate(v2.get_angle_between(v))
|
||||
angle = v.get_angle_between(v2)
|
||||
self.assertAlmostEquals(v.get_angle_between(v2), 0)
|
||||
|
||||
def testHighLevel(self):
|
||||
basis0 = vec2d(5.0, 0)
|
||||
basis1 = vec2d(0, .5)
|
||||
v = vec2d(10, 1)
|
||||
self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])
|
||||
self.assert_(v.projection(basis0) == (10, 0))
|
||||
self.assert_(basis0.dot(basis1) == 0)
|
||||
|
||||
def testCross(self):
|
||||
lhs = vec2d(1, .5)
|
||||
rhs = vec2d(4,6)
|
||||
self.assert_(lhs.cross(rhs) == 4)
|
||||
|
||||
def testComparison(self):
|
||||
int_vec = vec2d(3, -2)
|
||||
flt_vec = vec2d(3.0, -2.0)
|
||||
zero_vec = vec2d(0, 0)
|
||||
self.assert_(int_vec == flt_vec)
|
||||
self.assert_(int_vec != zero_vec)
|
||||
self.assert_((flt_vec == zero_vec) == False)
|
||||
self.assert_((flt_vec != int_vec) == False)
|
||||
self.assert_(int_vec == (3, -2))
|
||||
self.assert_(int_vec != [0, 0])
|
||||
self.assert_(int_vec != 5)
|
||||
self.assert_(int_vec != [3, -2, -5])
|
||||
|
||||
def testInplace(self):
|
||||
inplace_vec = vec2d(5, 13)
|
||||
inplace_ref = inplace_vec
|
||||
inplace_src = vec2d(inplace_vec)
|
||||
inplace_vec *= .5
|
||||
inplace_vec += .5
|
||||
inplace_vec /= (3, 6)
|
||||
inplace_vec += vec2d(-1, -1)
|
||||
alternate = (inplace_src*.5 + .5)/vec2d(3,6) + [-1, -1]
|
||||
self.assertEquals(inplace_vec, inplace_ref)
|
||||
self.assertEquals(inplace_vec, alternate)
|
||||
|
||||
def testPickle(self):
|
||||
testvec = vec2d(5, .3)
|
||||
testvec_str = pickle.dumps(testvec)
|
||||
loaded_vec = pickle.loads(testvec_str)
|
||||
self.assertEquals(testvec, loaded_vec)
|
||||
|
||||
####################################################################
|
||||
unittest.main()
|
||||
|
||||
########################################################################
|
||||
|
||||
def __setstate__(self, adict):
|
||||
self.x, self.y = adict
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user