Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton
2017-04-09 16:09:12 +10:00
14 changed files with 306 additions and 175 deletions

View File

@@ -94,6 +94,10 @@ set(OPENCOLORIO_OPENCOLORIO_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libOpenColorIO.
set(OPENCOLORIO_TINYXML_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libtinyxml.a" CACHE STRING "" FORCE)
set(OPENCOLORIO_YAML-CPP_LIBRARY "${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp.a" CACHE STRING "" FORCE)
# Freetype
set(FREETYPE_INCLUDE_DIRS "/usr/include/freetype2" CACHE STRING "" FORCE)
set(FREETYPE_LIBRARY "/usr/lib${MULTILIB}/libfreetype.a" CACHE STRING "" FORCE)
# OpenImageIO
if(GLIBC EQUAL "2.19")
set(OPENIMAGEIO_LIBRARY
@@ -102,6 +106,7 @@ if(GLIBC EQUAL "2.19")
/usr/lib${MULTILIB}/libwebp.a
/usr/lib${MULTILIB}/liblzma.a
/usr/lib${MULTILIB}/libjbig.a
${FREETYPE_LIBRARY}
CACHE STRING "" FORCE
)
endif()

View File

@@ -60,7 +60,7 @@ FIND_FILE(OPENIMAGEIO_IDIFF
NAMES
idiff
HINTS
${OPENIMAGEIO_ROOT_DIR}
${_openimageio_SEARCH_DIRS}
PATH_SUFFIXES
bin
)

View File

@@ -39,6 +39,9 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST)
${PTHREADS_LIBRARIES}
extern_glog
extern_gflags)
if(WITH_OPENMP_STATIC)
target_link_libraries(${NAME}_test ${OpenMP_LIBRARIES})
endif()
set_target_properties(${NAME}_test PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TESTS_OUTPUT_DIR}"

View File

@@ -1613,7 +1613,7 @@ int2 CUDASplitKernel::split_kernel_local_size()
return make_int2(32, 1);
}
int2 CUDASplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memory& /*data*/, DeviceTask */*task*/)
int2 CUDASplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memory& /*data*/, DeviceTask * /*task*/)
{
/* TODO(mai): implement something here to detect ideal work size */
return make_int2(256, 256);

View File

@@ -340,7 +340,7 @@ public:
return make_int2(64, 1);
}
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask */*task*/)
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask * /*task*/)
{
cl_device_type type = OpenCLInfo::get_device_type(device->cdDevice);
/* Use small global size on CPU devices as it seems to be much faster. */

View File

@@ -316,184 +316,203 @@ template<typename T> struct texture_image {
return interp_3d_ex(x, y, z, interpolation);
}
ccl_always_inline float4 interp_3d_ex(float x, float y, float z,
int interpolation = INTERPOLATION_LINEAR)
ccl_always_inline float4 interp_3d_ex_closest(float x, float y, float z)
{
if(UNLIKELY(!data))
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
int ix, iy, iz;
frac(x*(float)width, &ix);
frac(y*(float)height, &iy);
frac(z*(float)depth, &iz);
int ix, iy, iz, nix, niy, niz;
if(interpolation == INTERPOLATION_CLOSEST) {
frac(x*(float)width, &ix);
frac(y*(float)height, &iy);
frac(z*(float)depth, &iz);
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
/* Fall through. */
case EXTENSION_EXTEND:
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
return read(data[ix + iy*width + iz*width*height]);
}
/* Fall through. */
case EXTENSION_EXTEND:
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
else if(interpolation == INTERPOLATION_LINEAR) {
float tx = frac(x*(float)width - 0.5f, &ix);
float ty = frac(y*(float)height - 0.5f, &iy);
float tz = frac(z*(float)depth - 0.5f, &iz);
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
return read(data[ix + iy*width + iz*width*height]);
}
nix = wrap_periodic(ix+1, width);
niy = wrap_periodic(iy+1, height);
niz = wrap_periodic(iz+1, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
/* Fall through. */
case EXTENSION_EXTEND:
nix = wrap_clamp(ix+1, width);
niy = wrap_clamp(iy+1, height);
niz = wrap_clamp(iz+1, depth);
ccl_always_inline float4 interp_3d_ex_linear(float x, float y, float z)
{
int ix, iy, iz;
int nix, niy, niz;
float tx = frac(x*(float)width - 0.5f, &ix);
float ty = frac(y*(float)height - 0.5f, &iy);
float tz = frac(z*(float)depth - 0.5f, &iz);
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
nix = wrap_periodic(ix+1, width);
niy = wrap_periodic(iy+1, height);
niz = wrap_periodic(iz+1, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
}
/* Fall through. */
case EXTENSION_EXTEND:
nix = wrap_clamp(ix+1, width);
niy = wrap_clamp(iy+1, height);
niz = wrap_clamp(iz+1, depth);
float4 r;
r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + iz*width*height]);
r += (1.0f - tz)*(1.0f - ty)*tx*read(data[nix + iy*width + iz*width*height]);
r += (1.0f - tz)*ty*(1.0f - tx)*read(data[ix + niy*width + iz*width*height]);
r += (1.0f - tz)*ty*tx*read(data[nix + niy*width + iz*width*height]);
r += tz*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + niz*width*height]);
r += tz*(1.0f - ty)*tx*read(data[nix + iy*width + niz*width*height]);
r += tz*ty*(1.0f - tx)*read(data[ix + niy*width + niz*width*height]);
r += tz*ty*tx*read(data[nix + niy*width + niz*width*height]);
return r;
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
else {
/* Tricubic b-spline interpolation. */
const float tx = frac(x*(float)width - 0.5f, &ix);
const float ty = frac(y*(float)height - 0.5f, &iy);
const float tz = frac(z*(float)depth - 0.5f, &iz);
int pix, piy, piz, nnix, nniy, nniz;
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
float4 r;
pix = wrap_periodic(ix-1, width);
piy = wrap_periodic(iy-1, height);
piz = wrap_periodic(iz-1, depth);
r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + iz*width*height]);
r += (1.0f - tz)*(1.0f - ty)*tx*read(data[nix + iy*width + iz*width*height]);
r += (1.0f - tz)*ty*(1.0f - tx)*read(data[ix + niy*width + iz*width*height]);
r += (1.0f - tz)*ty*tx*read(data[nix + niy*width + iz*width*height]);
nix = wrap_periodic(ix+1, width);
niy = wrap_periodic(iy+1, height);
niz = wrap_periodic(iz+1, depth);
r += tz*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + niz*width*height]);
r += tz*(1.0f - ty)*tx*read(data[nix + iy*width + niz*width*height]);
r += tz*ty*(1.0f - tx)*read(data[ix + niy*width + niz*width*height]);
r += tz*ty*tx*read(data[nix + niy*width + niz*width*height]);
nnix = wrap_periodic(ix+2, width);
nniy = wrap_periodic(iy+2, height);
nniz = wrap_periodic(iz+2, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
/* Fall through. */
case EXTENSION_EXTEND:
pix = wrap_clamp(ix-1, width);
piy = wrap_clamp(iy-1, height);
piz = wrap_clamp(iz-1, depth);
return r;
}
nix = wrap_clamp(ix+1, width);
niy = wrap_clamp(iy+1, height);
niz = wrap_clamp(iz+1, depth);
ccl_never_inline float4 interp_3d_ex_tricubic(float x, float y, float z)
{
int ix, iy, iz;
int nix, niy, niz;
/* Tricubic b-spline interpolation. */
const float tx = frac(x*(float)width - 0.5f, &ix);
const float ty = frac(y*(float)height - 0.5f, &iy);
const float tz = frac(z*(float)depth - 0.5f, &iz);
int pix, piy, piz, nnix, nniy, nniz;
nnix = wrap_clamp(ix+2, width);
nniy = wrap_clamp(iy+2, height);
nniz = wrap_clamp(iz+2, depth);
switch(extension) {
case EXTENSION_REPEAT:
ix = wrap_periodic(ix, width);
iy = wrap_periodic(iy, height);
iz = wrap_periodic(iz, depth);
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
pix = wrap_periodic(ix-1, width);
piy = wrap_periodic(iy-1, height);
piz = wrap_periodic(iz-1, depth);
nix = wrap_periodic(ix+1, width);
niy = wrap_periodic(iy+1, height);
niz = wrap_periodic(iz+1, depth);
nnix = wrap_periodic(ix+2, width);
nniy = wrap_periodic(iy+2, height);
nniz = wrap_periodic(iz+2, depth);
break;
case EXTENSION_CLIP:
if(x < 0.0f || y < 0.0f || z < 0.0f ||
x > 1.0f || y > 1.0f || z > 1.0f)
{
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
}
/* Fall through. */
case EXTENSION_EXTEND:
pix = wrap_clamp(ix-1, width);
piy = wrap_clamp(iy-1, height);
piz = wrap_clamp(iz-1, depth);
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {width * piy,
width * iy,
width * niy,
width * nniy};
const int zc[4] = {width * height * piz,
width * height * iz,
width * height * niz,
width * height * nniz};
float u[4], v[4], w[4];
nix = wrap_clamp(ix+1, width);
niy = wrap_clamp(iy+1, height);
niz = wrap_clamp(iz+1, depth);
/* Some helper macro to keep code reasonable size,
* let compiler to inline all the matrix multiplications.
*/
nnix = wrap_clamp(ix+2, width);
nniy = wrap_clamp(iy+2, height);
nniz = wrap_clamp(iz+2, depth);
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
const int xc[4] = {pix, ix, nix, nnix};
const int yc[4] = {width * piy,
width * iy,
width * niy,
width * nniy};
const int zc[4] = {width * height * piz,
width * height * iz,
width * height * niz,
width * height * nniz};
float u[4], v[4], w[4];
/* Some helper macro to keep code reasonable size,
* let compiler to inline all the matrix multiplications.
*/
#define DATA(x, y, z) (read(data[xc[x] + yc[y] + zc[z]]))
#define COL_TERM(col, row) \
(v[col] * (u[0] * DATA(0, col, row) + \
u[1] * DATA(1, col, row) + \
u[2] * DATA(2, col, row) + \
u[3] * DATA(3, col, row)))
(v[col] * (u[0] * DATA(0, col, row) + \
u[1] * DATA(1, col, row) + \
u[2] * DATA(2, col, row) + \
u[3] * DATA(3, col, row)))
#define ROW_TERM(row) \
(w[row] * (COL_TERM(0, row) + \
COL_TERM(1, row) + \
COL_TERM(2, row) + \
COL_TERM(3, row)))
(w[row] * (COL_TERM(0, row) + \
COL_TERM(1, row) + \
COL_TERM(2, row) + \
COL_TERM(3, row)))
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
SET_CUBIC_SPLINE_WEIGHTS(w, tz);
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
SET_CUBIC_SPLINE_WEIGHTS(w, tz);
/* Actual interpolation. */
return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
/* Actual interpolation. */
return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
#undef COL_TERM
#undef ROW_TERM
#undef DATA
}
ccl_always_inline float4 interp_3d_ex(float x, float y, float z,
int interpolation = INTERPOLATION_LINEAR)
{
if(UNLIKELY(!data))
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
switch(interpolation) {
case INTERPOLATION_CLOSEST:
return interp_3d_ex_closest(x, y, z);
case INTERPOLATION_LINEAR:
return interp_3d_ex_linear(x, y, z);
default:
return interp_3d_ex_tricubic(x, y, z);
}
}

View File

@@ -33,6 +33,7 @@
#include <cuda.h>
#include <cuda_fp16.h>
#include <float.h>
#include <stdint.h>
/* Qualifier wrappers for different names on different devices */

View File

@@ -55,6 +55,7 @@
#endif
#define ccl_may_alias
#define ccl_always_inline __forceinline
#define ccl_never_inline __declspec(noinline)
#define ccl_maybe_unused
#else
@@ -68,6 +69,7 @@
#define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
#define ccl_may_alias __attribute__((__may_alias__))
#define ccl_always_inline __attribute__((always_inline))
#define ccl_never_inline __attribute__((noinline))
#define ccl_maybe_unused __attribute__((used))
#endif

View File

@@ -209,6 +209,8 @@ class HomographySymmetricGeometricCostFunctor {
return true;
}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
const Vec2 x_;
const Vec2 y_;
};

View File

@@ -140,6 +140,78 @@ KM_HIERARCHY = [
]
# -----------------------------------------------------------------------------
# Add-on helpers to properly (un)register their own keymaps.
# Example of keymaps_description:
keymaps_description_doc = """
keymaps_description is a tuple (((keymap_description), (tuple of keymap_item_descriptions))).
keymap_description is a tuple (name, space_type, region_type, is_modal).
keymap_item_description is a tuple ({kw_args_for_keymap_new}, (tuple of properties)).
kw_args_for_keymap_new is a mapping which keywords match parameters of keymap.new() function.
tuple of properties is a tuple of pairs (prop_name, prop_value) (properties being those of called operator).
Example:
KEYMAPS = (
# First, keymap identifiers (last bool is True for modal km).
(('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', False), (
# Then a tuple of keymap items, defined by a dict of kwargs for the km new func, and a tuple of tuples (name, val)
# for ops properties, if needing non-default values.
({"idname": export_strips.SEQExportStrip.bl_idname, "type": 'P', "value": 'PRESS', "shift": True, "ctrl": True},
()),
)),
)
"""
def addon_keymap_register(wm, keymaps_description):
"""
Register a set of keymaps for addons.
""" + keymaps_description_doc
kconf = wm.keyconfigs.addon
if not kconf:
return # happens in background mode...
for km_info, km_items in keymaps_description:
km_name, km_sptype, km_regtype, km_ismodal = km_info
kmap = [k for k in kconf.keymaps
if k.name == km_name and k.region_type == km_regtype and
k.space_type == km_sptype and k.is_modal == km_ismodal]
if kmap:
kmap = kmap[0]
else:
kmap = kconf.keymaps.new(km_name, region_type=km_regtype, space_type=km_sptype, modal=km_ismodal)
for kmi_kwargs, props in km_items:
kmi = kmap.keymap_items.new(**kmi_kwargs)
kmi.active = True
for prop, val in props:
setattr(kmi.properties, prop, val)
def addon_keymap_unregister(wm, keymaps_description):
"""
Unregister a set of keymaps for addons.
""" + keymaps_description_doc
# NOTE: We must also clean up user keyconfig, else, if user has customized one of add-on's shortcut, this
# customization remains in memory, and comes back when re-enabling the addon, causing a segfault... :/
kconfs = wm.keyconfigs
for kconf in (kconfs.user, kconfs.addon):
for km_info, km_items in keymaps_description:
km_name, km_sptype, km_regtype, km_ismodal = km_info
kmaps = (k for k in kconf.keymaps
if k.name == km_name and k.region_type == km_regtype and
k.space_type == km_sptype and k.is_modal == km_ismodal)
for kmap in kmaps:
for kmi_kwargs, props in km_items:
idname = kmi_kwargs["idname"]
for kmi in kmap.keymap_items:
if kmi.idname == idname:
kmap.keymap_items.remove(kmi)
# NOTE: We won't remove addons keymaps themselves, other addons might also use them!
# -----------------------------------------------------------------------------
# Utility functions

View File

@@ -504,14 +504,9 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
break;
default:
{
IDProperty *tmp = other;
IDProperty *copy = IDP_CopyProperty(prop);
BLI_insertlinkafter(&dest->data.group, other, copy);
BLI_remlink(&dest->data.group, tmp);
IDP_FreeProperty(tmp);
MEM_freeN(tmp);
BLI_insertlinkreplace(&dest->data.group, other, IDP_CopyProperty(prop));
IDP_FreeProperty(other);
MEM_freeN(other);
break;
}
}
@@ -531,11 +526,9 @@ void IDP_SyncGroupTypes(IDProperty *dst, const IDProperty *src, const bool do_ar
if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) ||
(do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) && (prop_src->len != prop_dst->len)))
{
IDP_FreeFromGroup(dst, prop_dst);
prop_dst = IDP_CopyProperty(prop_src);
dst->len++;
BLI_insertlinkbefore(&dst->data.group, prop_dst_next, prop_dst);
BLI_insertlinkreplace(&dst->data.group, prop_dst, IDP_CopyProperty(prop_src));
IDP_FreeProperty(prop_dst);
MEM_freeN(prop_dst);
}
else if (prop_dst->type == IDP_GROUP) {
IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen);
@@ -560,11 +553,7 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
for (prop = src->data.group.first; prop; prop = prop->next) {
for (loop = dest->data.group.first; loop; loop = loop->next) {
if (STREQ(loop->name, prop->name)) {
IDProperty *copy = IDP_CopyProperty(prop);
BLI_insertlinkafter(&dest->data.group, loop, copy);
BLI_remlink(&dest->data.group, loop);
BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop));
IDP_FreeProperty(loop);
MEM_freeN(loop);
break;
@@ -591,9 +580,7 @@ void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop
BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name));
if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) {
BLI_insertlinkafter(&group->data.group, prop_exist, prop);
BLI_remlink(&group->data.group, prop_exist);
BLI_insertlinkreplace(&group->data.group, prop_exist, prop);
IDP_FreeProperty(prop_exist);
MEM_freeN(prop_exist);
}

View File

@@ -67,6 +67,7 @@ void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1);
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1);
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1);
void BLI_insertlinkreplace(ListBase *listbase, void *v_l_src, void *v_l_dst) ATTR_NONNULL(1, 2, 3);
void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2);
void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2);
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL();

View File

@@ -370,6 +370,40 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
}
}
/**
* Insert a link in place of another, without changing it's position in the list.
*
* Puts `vnewlink` in the position of `vreplacelink`, removing `vreplacelink`.
* - `vreplacelink` *must* be in the list.
* - `vnewlink` *must not* be in the list.
*/
void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink)
{
Link *l_old = vreplacelink;
Link *l_new = vnewlink;
/* update adjacent links */
if (l_old->next != NULL) {
l_old->next->prev = l_new;
}
if (l_old->prev != NULL) {
l_old->prev->next = l_new;
}
/* set direct links */
l_new->next = l_old->next;
l_new->prev = l_old->prev;
/* update list */
if (listbase->first == l_old) {
listbase->first = l_new;
}
if (listbase->last == l_old) {
listbase->last = l_new;
}
}
/**
* Reinsert \a vlink relative to its current position but offset by \a step. Doesn't move
* item if new position would exceed list (could optionally move to head/tail).

View File

@@ -260,6 +260,11 @@ class KDTreeTesting(unittest.TestCase):
k.balance()
return k
def assertAlmostEqualVector(self, first, second, places=7, msg=None, delta=None):
self.assertAlmostEqual(first[0], second[0], places=places, msg=msg, delta=delta)
self.assertAlmostEqual(first[1], second[1], places=places, msg=msg, delta=delta)
self.assertAlmostEqual(first[2], second[2], places=places, msg=msg, delta=delta)
def test_kdtree_single(self):
co = (0,) * 3
index = 2
@@ -360,12 +365,12 @@ class KDTreeTesting(unittest.TestCase):
ret_regular = k_odd.find(co)
self.assertEqual(ret_regular[1] % 2, 1)
ret_filter = k_all.find(co, lambda i: (i % 2) == 1)
self.assertEqual(ret_regular, ret_filter)
self.assertAlmostEqualVector(ret_regular, ret_filter)
ret_regular = k_evn.find(co)
self.assertEqual(ret_regular[1] % 2, 0)
ret_filter = k_all.find(co, lambda i: (i % 2) == 0)
self.assertEqual(ret_regular, ret_filter)
self.assertAlmostEqualVector(ret_regular, ret_filter)
# filter out all values (search odd tree for even values and the reverse)