Commit 0ac2f1c8 authored by Scott Wittenburg's avatar Scott Wittenburg Committed by Kitware Robot

Merge topic 'context2d-add-vtkpythonitem'

1c68049f Add a test demonstrating the use of vtkPythonItem
f055428b Provide a simple python Context2D item, similar to vtkPythonAlgorithm
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !4727
parents aba25924 1c68049f
set(module_SRCS
vtkPythonItem.cxx
)
vtk_module_library(vtkPythonContext2D ${module_SRCS})
69efe0b7307942844762db383e8752beca8041a28f408c57778bd06569b3febb8973f1dc41d6ceb02555465f417405516f4406a1221d3d906eaf15962ee293cc
vtk_add_test_python(
testPythonItem.py
)
import sys
import vtk
from vtk.test import Testing
class CustomPythonItem(object):
def __init__(self, polydata):
self.polydata = polydata
def Initialize(self, vtkSelf):
return True
def Paint(self, vtkSelf, context2D):
context2D.DrawPolyData(0.0,
0.0,
self.polydata,
self.polydata.GetCellData().GetScalars(),
vtk.VTK_SCALAR_MODE_USE_CELL_DATA)
pen = context2D.GetPen()
penColor = [0, 0, 0]
pen.GetColor(penColor)
penWidth = pen.GetWidth()
brush = context2D.GetBrush()
brushColor = [0, 0, 0, 0]
brush.GetColor(brushColor)
pen.SetColor([0, 0, 255])
brush.SetColor([0, 0, 255])
context2D.DrawWedge(0.75, 0.25, 0.125, 0.005, 30.0, 60.0)
pen.SetWidth(20.0)
pen.SetColor([0, 0, 0])
brush.SetColor([0, 0, 0])
context2D.DrawMarkers(vtk.vtkMarkerUtilities.CIRCLE, False, [0.1, 0.1, 0.5, 0.5, 0.9, 0.9], 3)
pen.SetWidth(1.0)
textProp = vtk.vtkTextProperty()
textProp.BoldOn()
textProp.ItalicOn()
textProp.SetFontSize(22)
textProp.SetColor(0.5, 0.0, 1.0)
textProp.SetOrientation(45)
context2D.ApplyTextProp(textProp)
context2D.DrawString(0.35, 0.4, b"Context2D!")
pen.SetColor([200, 200, 30])
brush.SetColor([200, 200, 30])
brush.SetOpacity(128)
context2D.DrawPolygon([0.5, 0.5, 0.75, 0.0, 1.0, 0.5], 3)
pen.SetColor([133, 70, 70])
brush.SetColor([133, 70, 70])
brush.SetOpacity(255)
context2D.DrawArc(0.25, 0.75, 0.125, 0.0, 360.0)
pen.SetWidth(penWidth)
pen.SetColor(penColor)
brush.SetColor(brushColor[:3])
brush.SetOpacity(brushColor[3])
return True
def buildPolyData():
pd = vtk.vtkPolyData()
pts = vtk.vtkPoints()
pts.InsertNextPoint([0.1, 0.1, 0.0])
pts.InsertNextPoint([0.9, 0.9, 0.0])
pd.SetPoints(pts)
lines = vtk.vtkCellArray()
lines.InsertNextCell(2)
lines.InsertCellPoint(0)
lines.InsertCellPoint(1)
pd.SetLines(lines)
colors = vtk.vtkUnsignedCharArray()
colors.SetNumberOfComponents(4)
colors.InsertNextTypedTuple([27, 128, 89, 255])
pd.GetCellData().SetScalars(colors)
return pd
class TestPythonItem(Testing.vtkTest):
def testPythonItem(self):
width = 400
height = 400
view = vtk.vtkContextView()
renWin = view.GetRenderWindow()
renWin.SetSize(width, height)
area = vtk.vtkInteractiveArea()
view.GetScene().AddItem(area)
drawAreaBounds = vtk.vtkRectd(0.0, 0.0, 1.0, 1.0)
vp = [0.05, 0.95, 0.05, 0.95]
screenGeometry = vtk.vtkRecti(int(vp[0] * width),
int(vp[2] * height),
int((vp[1] - vp[0]) * width),
int((vp[3] - vp[2]) * height))
item = vtk.vtkPythonItem()
item.SetPythonObject(CustomPythonItem(buildPolyData()))
item.SetVisible(True)
area.GetDrawAreaItem().AddItem(item)
area.SetDrawAreaBounds(drawAreaBounds)
area.SetGeometry(screenGeometry)
area.SetFillViewport(False)
area.SetShowGrid(False)
axisLeft = area.GetAxis(vtk.vtkAxis.LEFT)
axisRight = area.GetAxis(vtk.vtkAxis.RIGHT)
axisBottom = area.GetAxis(vtk.vtkAxis.BOTTOM)
axisTop = area.GetAxis(vtk.vtkAxis.TOP)
axisTop.SetVisible(False)
axisRight.SetVisible(False)
axisLeft.SetVisible(False)
axisBottom.SetVisible(False)
axisTop.SetMargins(0, 0)
axisRight.SetMargins(0, 0)
axisLeft.SetMargins(0, 0)
axisBottom.SetMargins(0, 0)
renWin.Render()
# Create a vtkTesting object
rtTester = vtk.vtkTesting()
rtTester.SetRenderWindow(renWin)
for arg in sys.argv[1:]:
rtTester.AddArgument(arg)
# Perform the image comparison test and print out the result.
result = rtTester.RegressionTest(0.0)
if result == 0:
raise Exception("TestPythonItem failed.")
if __name__ == "__main__":
Testing.main([(TestPythonItem, 'test')])
if (VTK_WRAP_PYTHON)
vtk_module(vtkPythonContext2D
GROUPS
StandAlone
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_JAVA_WRAPPING
TEST_DEPENDS
vtkTestingCore
KIT
vtkWrapping
DEPENDS
vtkRenderingContext2D
PRIVATE_DEPENDS
vtkCommonCore
vtkWrappingPythonCore
)
endif ()
/*=========================================================================
Program: Visualization Toolkit
Module: vtkPythonItem.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkPythonItem.h"
#include "vtkObjectFactory.h"
#include "vtkContext2D.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkPythonUtil.h"
#include "vtkSmartPyObject.h"
vtkStandardNewMacro(vtkPythonItem);
//------------------------------------------------------------------------------
void vtkPythonItem::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
vtkPythonScopeGilEnsurer gilEnsurer;
vtkSmartPyObject str;
if (this->Object)
{
str.TakeReference(PyObject_Str(this->Object));
}
os << indent << "Object: " << Object << std::endl;
if (str)
{
os << indent << "Object (string): ";
#ifndef VTK_PY3K
os << PyString_AsString(str);
#else
PyObject *bytes = PyUnicode_EncodeLocale(str, VTK_PYUNICODE_ENC);
if (bytes)
{
os << PyBytes_AsString(bytes);
Py_DECREF(bytes);
}
#endif
os << std::endl;
}
}
//------------------------------------------------------------------------------
vtkPythonItem::vtkPythonItem()
{
this->Object = nullptr;
}
//------------------------------------------------------------------------------
vtkPythonItem::~vtkPythonItem()
{
// we check if Python is still initialized since the Python interpreter may
// have been finalized before the VTK object is released.
if (Py_IsInitialized())
{
vtkPythonScopeGilEnsurer gilEnsurer;
Py_XDECREF(this->Object);
}
}
// This macro gets the method passed in as the parameter method
// from the PyObject passed in as the parameter obj and creates a
// vtkSmartPyObject variable with the name passed in as the parameter
// var containing that method's PyObject. If obj is nullptr, obj.method
// does not exist or obj.method is not a callable method, this macro
// causes the function using it to return with the return value
// passed in as the parameter failValue
// var - the name of the resulting vtkSmartPyObject with the
// method object in it. Can be used in the code following
// the macro's use as the variable name
// obj - the PyObject to get the method from
// method - the name of the method to look for. Should be a
// C string.
// failValue - the value to return if the lookup fails and the
// function using the macro should return. Pass in a
// block comment /**/ for void functions using this macro
#define VTK_GET_METHOD(var, obj, method, failValue) \
if (!(obj)) \
{ \
return failValue; \
} \
vtkSmartPyObject var(PyObject_GetAttrString(obj, method)); \
if (!(var)) \
{ \
return failValue; \
} \
if (!PyCallable_Check(var)) \
{ \
return failValue; \
}
//------------------------------------------------------------------------------
static PyObject* VTKToPython(vtkObjectBase* obj)
{
// Return value: New reference.
return vtkPythonUtil::GetObjectFromPointer(obj);
}
//------------------------------------------------------------------------------
bool vtkPythonItem::CheckResult(const char* method, const vtkSmartPyObject &res)
{
vtkPythonScopeGilEnsurer gilEnsurer;
if (!res)
{
vtkErrorMacro("Failure when calling method: \"" << method << "\":");
if (PyErr_Occurred() != nullptr)
{
PyErr_Print();
PyErr_Clear();
}
return false;
}
if (!PyBool_Check(res))
{
vtkWarningMacro("The method \"" << method << "\" should have returned boolean but did not")
return false;
}
if (res == Py_False)
{
return false;
}
return true;
}
//------------------------------------------------------------------------------
void vtkPythonItem::SetPythonObject(PyObject* obj)
{
vtkPythonScopeGilEnsurer gilEnsurer;
if (!obj)
{
return;
}
Py_XDECREF(this->Object);
this->Object = obj;
Py_INCREF(this->Object);
char mname[] = "Initialize";
VTK_GET_METHOD(method, this->Object, mname, /* no return */)
vtkSmartPyObject args(PyTuple_New(1));
PyObject* vtkself = VTKToPython(this);
PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
CheckResult(mname, result);
}
//------------------------------------------------------------------------------
bool vtkPythonItem::Paint(vtkContext2D *painter)
{
vtkPythonScopeGilEnsurer gilEnsurer;
char mname[] = "Paint";
VTK_GET_METHOD(method, this->Object, mname, 0)
vtkSmartPyObject args(PyTuple_New(2));
PyObject* vtkself = VTKToPython(this);
PyTuple_SET_ITEM(args.GetPointer(), 0, vtkself);
PyObject* pypainter = VTKToPython(painter);
PyTuple_SET_ITEM(args.GetPointer(), 1, pypainter);
vtkSmartPyObject result(PyObject_Call(method, args, nullptr));
return CheckResult(mname, result);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkPythonItem.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkPythonItem
* @brief A vtkContextItem that can be implemented in Python
*
*
* This class allows implementation of arbitrary context items in Python.
*
* @sa
* vtkAbstractContextItem
*/
#ifndef vtkPythonItem_h
#define vtkPythonItem_h
#if !defined(__VTK_WRAP__) || defined(__VTK_WRAP_HIERARCHY__) || defined(__VTK_WRAP_PYTHON__)
#include "vtkPython.h" // Must be first
#include "vtkPythonContext2DModule.h" // For export macro
#include "vtkContextItem.h"
class vtkSmartPyObject;
class VTKPYTHONCONTEXT2D_EXPORT vtkPythonItem : public vtkContextItem
{
public:
vtkTypeMacro(vtkPythonItem, vtkContextItem);
void PrintSelf(ostream &os, vtkIndent indent) override;
static vtkPythonItem * New();
/**
* Specify the Python object to use to operate on the data. A reference will
* be taken on the object. This will also invoke Initialize() on the Python
* object, providing an opportunity to perform tasks commonly done in the
* constructor of C++ vtkContextItem subclasses.
*/
void SetPythonObject(PyObject* obj);
bool Paint(vtkContext2D *painter) override;
protected:
vtkPythonItem();
~vtkPythonItem() override;
private:
vtkPythonItem(const vtkPythonItem &) = delete;
void operator=(const vtkPythonItem &) = delete;
bool CheckResult(const char* method, const vtkSmartPyObject& res);
PyObject* Object;
};
#endif // #ifndef vtkPythonItem_h
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment