Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ Unreleased

**Removed**

0.2.1
----------
**Changed**

* updated dependencies ``compas`` from 1.17 to 2.13

0.2.0
----------

Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ isort
pydocstyle
pylint
pytest
rhino3dm # Used only for testing
rhino3dm>=8.17 # Used only for testing
sphinx >=1.6
sphinx_compas_theme >=0.13
-e .
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
compas>=2.13
geomdl>=5.4

25 changes: 20 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from __future__ import absolute_import, print_function

import io
import re
from glob import glob
from os.path import abspath, basename, dirname, join, splitext

from setuptools import find_packages, setup

requirements = [
'compas>=1.0,<2.0',
]
from pathlib import Path

here = Path(__file__).parent

def read_requirements(filename: str) -> list[str]:
req_path = here / filename
if not req_path.exists():
return []
lines = req_path.read_text(encoding="utf-8").splitlines()
reqs = []
for line in lines:
s = line.strip()
# skip comments/empties and nested includes
if not s or s.startswith("#") or s.startswith(("-r ", "--requirement ")):
continue
reqs.append(s)
return reqs


keywords_list = ['compas', 'nurbs', 'rhino', 'bspline']

here = abspath(dirname(__file__))
Expand Down Expand Up @@ -64,7 +79,7 @@ def read(*names, **kwargs):
'Topic :: Scientific/Engineering',
],
keywords=keywords_list,
install_requires=requirements,
install_requires=read_requirements("requirements.txt"),
extras_require={},
entry_points={},
)
4 changes: 2 additions & 2 deletions src/compas_nurbs/bspline.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import compas
from compas.geometry import Primitive
from compas.geometry import Geometry

from compas_nurbs.knot_vectors import check_knot_vector
from compas_nurbs.knot_vectors import knot_vector_uniform
Expand All @@ -16,7 +16,7 @@
from collections import Iterable


class BSpline(Primitive):
class BSpline(Geometry):
"""A base class for rational and non-rational B-Spline geometry.

Contains all setters and checkers.
Expand Down
4 changes: 3 additions & 1 deletion src/compas_nurbs/curvature.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def radius(self):
@property
def osculating_circle(self):
center = self.frame.point + self.radius * self.normal
return Circle(Plane(center, self.frame.zaxis), self.radius)
plane = Plane(center, self.frame.zaxis)
circle = Circle.from_plane_and_radius(plane, radius=self.radius)
return circle


class SurfaceCurvature(object):
Expand Down
3 changes: 1 addition & 2 deletions src/compas_nurbs/evaluators.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import scipy
import numpy as np
from geomdl.linalg import binomial_coefficient

from .helpers import find_spans
from .helpers import basis_functions
from .helpers import basis_functions_derivatives

from compas.geometry.primitives.curve import binomial_coefficient # TODO compas: move this upwards

# ==============================================================================
# curve
# ==============================================================================
Expand Down
2 changes: 1 addition & 1 deletion src/compas_nurbs/knot_vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def bezier_spaced_parameters(num_points):
If degree >= 5 this provides a more stable knotvector for 'uniform' knot style.
"""
curve = Bezier([[0.0, 0.0, 0.0], [0.5, 0.0, 0.0], [0.5, 1.0, 0.0], [1., 1., 0]])
return [curve.point(t).y for t in equally_spaced_parameters(num_points)]
return [curve.point_at(t).y for t in equally_spaced_parameters(num_points)]


def chord_lengths(points):
Expand Down
32 changes: 16 additions & 16 deletions tests/test_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
import rhino3dm
from geomdl import BSpline
from geomdl import NURBS
from compas.geometry import allclose
from compas.geometry import Point
from compas.geometry import Vector
from compas_nurbs import Curve
from compas_nurbs import RationalCurve

from compas.tolerance import TOL

def rhino_curve_from_curve(curve):
rhino_curve = rhino3dm.NurbsCurve(3, curve.rational, curve.degree + 1, curve.count)
Expand Down Expand Up @@ -47,32 +46,32 @@ def test_curve():
rhino_points = [curve_rhino.PointAt(t) for t in params]
rhino_points = [[p.X, p.Y, p.Z] for p in rhino_points]
geomdl_points = curve_geomdl.evaluate_list(params)
assert(allclose(points, rhino_points))
assert(allclose(points, geomdl_points))
assert(TOL.is_allclose(points, rhino_points))
assert(TOL.is_allclose(points, geomdl_points))

# derivatives
geomdl_derivatives = [curve_geomdl.derivatives(u, order=1) for u in params]
assert(allclose(geomdl_derivatives, curve.derivatives_at(params)))
assert(TOL.is_allclose(geomdl_derivatives, curve.derivatives_at(params)))

# tangents
tangents = curve.tangents_at(params)
rhino_tangents = [curve_rhino.TangentAt(t) for t in params]
rhino_tangents = [[p.X, p.Y, p.Z] for p in rhino_tangents]
geomdl_tangents = curve_geomdl.tangent(params)
assert(allclose(tangents, rhino_tangents))
assert(allclose(tangents, geomdl_tangents))
assert(TOL.is_allclose(tangents, rhino_tangents))
assert(TOL.is_allclose(tangents, geomdl_tangents))

# curvature
curvature = [c.curvature for c in curve.curvatures_at(params)]
rhino_curvature_vectors = [curve_rhino.CurvatureAt(t) for t in params]
rhino_curvature = [np.linalg.norm([p.X, p.Y, p.Z]) for p in rhino_curvature_vectors]
assert(allclose(curvature, rhino_curvature))
assert(TOL.is_allclose(curvature, rhino_curvature))
circle_centers = [c.osculating_circle.plane.point for c in curve.curvatures_at(params)]
rhino_centers = []
for pt, cv in zip(rhino_points, rhino_curvature_vectors):
cv = Vector(cv.X, cv.Y, cv.Z)
rhino_centers.append(Point(*pt) + cv.unitized() * 1/cv.length)
assert(allclose(circle_centers, rhino_centers))
assert(TOL.is_allclose(circle_centers, rhino_centers))


def test_rational_curve():
Expand Down Expand Up @@ -100,31 +99,32 @@ def test_rational_curve():
(1065.127, 189.409, 0.), (1109.071, 198.051, 0.), (1226.082, 218.523, 0.), (1348.823, 250.108, 0.),
(1438.406, 239.541, 0.), (1520.010, 156.330, 0.)]
geomdl_points = curve_geomdl.evaluate_list(params)
assert(allclose(points, rhino_points, tol=1e-03))
assert(allclose(points, geomdl_points))
assert(TOL.is_allclose(points, rhino_points, rtol=1e-03))
assert(TOL.is_allclose(points, geomdl_points))

# derivatives
geomdl_derivatives = [curve_geomdl.derivatives(u, order=1) for u in params]
assert(allclose(geomdl_derivatives, curve.derivatives_at(params)))
assert(TOL.is_allclose(geomdl_derivatives, curve.derivatives_at(params)))

# tangents
tangents = curve.tangents_at(params)
rhino_tangents = [(0.407, 0.913, 0.), (0.939, -0.345, 0.), (0.999, 0.033, 0.), (0.917, 0.400, 0.),
(0.954, 0.301, 0.), (0.989, 0.151, 0.), (0.977, 0.213, 0.), (0.977, 0.212, 0.),
(0.855, -0.518, 0.), (0.628, -0.778, 0.)]
geomdl_tangents = curve_geomdl.tangent(params)
assert(allclose(tangents, rhino_tangents, tol=1e-03))
assert(allclose(tangents, geomdl_tangents))
assert(TOL.is_allclose(tangents, rhino_tangents, rtol=1e-03, atol=1e-03))
assert(TOL.is_allclose(tangents, geomdl_tangents))

# curvature
curvature = [c.curvature for c in curve.curvatures_at(params)]
rhino_curvature = [0.000851, 0.000762, 0.013305, 0.006902, 0.009795, 0.00037, 0.000876, 0.003371, 0.008178, 5e-05]
assert(allclose(curvature, rhino_curvature))

TOL.is_allclose(curvature, rhino_curvature, rtol=1e-4, atol=1e-3)
circle_centers = [c.osculating_circle.plane.point for c in curve.curvatures_at(params)]
rhino_centers = [(1889.858, -338.654, 0.), (1396.986, 1424.413, 0.), (1017.561, 250.506, 0.), (988.023, 314.332, 0.),
(1095.819, 92.043, 0.), (1516.222, -2474.241, 0.), (982.641, 1333.837, 0.), (1411.820, -39.776, 0.),
(1375.058, 134.945, 0.), (-14154.272, -12485.585, 0.)]
assert(allclose(circle_centers, rhino_centers, tol=1e-03))
assert(TOL.is_allclose(circle_centers, rhino_centers, rtol=1e-03))


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions tests/test_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from compas.geometry import close
from compas.geometry import allclose
from compas.utilities import flatten
from compas.itertools import flatten

from compas_nurbs import Curve
from compas_nurbs import Surface
Expand Down Expand Up @@ -90,7 +90,7 @@ def test_surface():
rhino_curvature = {'direction': [[-0.93527, 0.3356, 0.11244], [-0.30401, -0.92441, 0.23033]], 'gauss': -
0.06905, 'mean': -0.12646, 'kappa': [-0.41808, 0.16516], 'normal': [0.18124, 0.18124, 0.9666]}
assert(allclose(curvature.direction, rhino_curvature['direction'], tol=0.01))
assert(allclose(curvature.kappa, rhino_curvature['kappa']))
assert(allclose(curvature.kappa, rhino_curvature['kappa'], tol=0.01))
assert(allclose(curvature.normal, rhino_curvature['normal'], tol=0.01))
assert(close(curvature.gauss, rhino_curvature['gauss']))
assert(close(curvature.mean, rhino_curvature['mean']))
Expand Down Expand Up @@ -128,7 +128,7 @@ def test_rational_surface():
[4.34132, 2.71191, -0.50399], [4.39635, 3.98729, -0.56116], [4.35627, 5.26156, -0.2744], [4.11864, 8.0, 0.88983], [6.0, 0.0, 0.0],
[6.0, 3.8, -2.475], [6.0, 4.57143, -2.35714], [6.0, 5.57143, -1.76786], [6.0, 8.0, 0.0]]
assert(allclose(points, geomdl_points))
assert(allclose(points, rhino_points))
assert(allclose(points, rhino_points, tol=0.01))

# derivatives
derivatives = surface.derivatives_at(params, order=1)
Expand All @@ -151,7 +151,7 @@ def test_rational_surface():
rhino_curvature = {'direction': [[-0.93542, 0.2192, 0.27737], [-0.20539, -0.97554, 0.07829]], 'gauss': -
0.06474, 'mean': -0.14782, 'kappa': [-0.44209, 0.14644], 'normal': [0.28774, 0.01626, 0.95757]}
assert(allclose(curvature.direction, rhino_curvature['direction'], tol=0.01))
assert(allclose(curvature.kappa, rhino_curvature['kappa']))
assert(allclose(curvature.kappa, rhino_curvature['kappa'], tol=0.01))
assert(allclose(curvature.normal, rhino_curvature['normal'], tol=0.01))
assert(close(curvature.gauss, rhino_curvature['gauss']))
assert(close(curvature.mean, rhino_curvature['mean']))
Expand Down Expand Up @@ -180,7 +180,7 @@ def test_isocurve():
degree_u = 3
degree_v = 2
surface = Surface(control_points_2d, (degree_u, degree_v))

curve = surface.isocurve(0, 0.5)
assert(allclose(curve.knot_vector, [0.0, 0.0, 0.0, 1.0, 1.0, 1.0]))
assert(allclose(curve.control_points, [[3.0, 0.0, 2.25], [3.0, 4.0, -0.375], [3.0, 8.0, 0.75]]))
Expand Down
Loading