├── .gitignore ├── .priority ├── CMakeLists.txt ├── FindPathPython.cmake ├── GeodeSupport.cmake ├── Jenkinsfile ├── LICENSE ├── README.md ├── bin ├── convert-case ├── draw-module-deps ├── draw-polygons ├── fix-various ├── symbol-counts └── trycat ├── geode.pc.in ├── geode ├── CMakeLists.txt ├── __init__.py ├── array │ ├── Array.cpp │ ├── Array.h │ ├── Array2d.cpp │ ├── Array2d.h │ ├── Array3d.h │ ├── Array4d.h │ ├── ArrayAbs.h │ ├── ArrayBase.h │ ├── ArrayDifference.h │ ├── ArrayExpression.h │ ├── ArrayIter.h │ ├── ArrayLeftMultiple.h │ ├── ArrayNdBase.h │ ├── ArrayNegation.h │ ├── ArrayPlusScalar.h │ ├── ArrayProduct.h │ ├── ArraySum.h │ ├── CMakeLists.txt │ ├── ConstantMap.h │ ├── Field.h │ ├── IndirectArray.h │ ├── NdArray.cpp │ ├── NdArray.h │ ├── Nested.cpp │ ├── Nested.h │ ├── NestedField.h │ ├── ProjectedArray.h │ ├── RawArray.cpp │ ├── RawArray.h │ ├── RawField.h │ ├── RawStack.h │ ├── SmallArray.h │ ├── Subarray.h │ ├── UntypedArray.h │ ├── __init__.py │ ├── alloca.h │ ├── amap.h │ ├── arange.h │ ├── convert.h │ ├── forward.h │ ├── module.cpp │ ├── permute.cpp │ ├── permute.h │ ├── reversed.h │ ├── sort.h │ ├── stencil.cpp │ ├── stencil.h │ ├── test_array.py │ ├── test_stencil.py │ └── view.h ├── config.h.in ├── core.vcxproj ├── core.vcxproj.filters ├── exact │ ├── CMakeLists.txt │ ├── Exact.cpp │ ├── Exact.h │ ├── ExactSegmentGraph.cpp │ ├── ExactSegmentGraph.h │ ├── Expansion.cpp │ ├── Expansion.h │ ├── Interval.cpp │ ├── Interval.h │ ├── PlanarArcGraph.cpp │ ├── PlanarArcGraph.h │ ├── __init__.py │ ├── circle_csg.cpp │ ├── circle_csg.h │ ├── circle_enums.h │ ├── circle_objects.cpp │ ├── circle_objects.h │ ├── circle_offsets.cpp │ ├── circle_offsets.h │ ├── circle_quantization.cpp │ ├── circle_quantization.h │ ├── collision.cpp │ ├── collision.h │ ├── config.h │ ├── constructions.cpp │ ├── constructions.h │ ├── debug.h │ ├── delaunay-test │ ├── delaunay.cpp │ ├── delaunay.h │ ├── exact-generated.h │ ├── exact_circle_offsets.cpp │ ├── exact_circle_offsets.h │ ├── find_overlapping_offsets.cpp │ ├── find_overlapping_offsets.h │ ├── forward.h │ ├── gen-exact │ ├── irreducible.cpp │ ├── irreducible.h │ ├── math.h │ ├── mesh_csg.cpp │ ├── mesh_csg.h │ ├── module.cpp │ ├── perturb.cpp │ ├── perturb.h │ ├── polygon_csg.cpp │ ├── polygon_csg.h │ ├── polynomial.cpp │ ├── polynomial.h │ ├── predicates.cpp │ ├── predicates.h │ ├── quantize.h │ ├── scope.h │ ├── simple_triangulate.cpp │ ├── simple_triangulate.h │ ├── test_circle.py │ ├── test_exact.py │ ├── test_mesh_csg.py │ └── test_perturb.py ├── force │ ├── AirPressure.cpp │ ├── AirPressure.h │ ├── AnisotropicConstitutiveModel.h │ ├── AxisPins.cpp │ ├── AxisPins.h │ ├── BindingSprings.cpp │ ├── BindingSprings.h │ ├── CMakeLists.txt │ ├── ConstitutiveModel.cpp │ ├── ConstitutiveModel.h │ ├── CubicHinges.cpp │ ├── CubicHinges.h │ ├── DiagonalizedIsotropicStressDerivative.cpp │ ├── DiagonalizedIsotropicStressDerivative.h │ ├── DiagonalizedStressDerivative.h │ ├── EtherDrag.cpp │ ├── EtherDrag.h │ ├── FiniteVolume.cpp │ ├── FiniteVolume.h │ ├── Force.cpp │ ├── Force.h │ ├── Gravity.cpp │ ├── Gravity.h │ ├── IsotropicConstitutiveModel.h │ ├── LinearBendingElements.cpp │ ├── LinearBendingElements.h │ ├── LinearFiniteVolume.cpp │ ├── LinearFiniteVolume.h │ ├── LinearFiniteVolumeHex.cpp │ ├── LinearFiniteVolumeHex.h │ ├── NeoHookean.cpp │ ├── ParticleBindingSprings.cpp │ ├── ParticleBindingSprings.h │ ├── Pins.cpp │ ├── Pins.h │ ├── PlasticityModel.cpp │ ├── PlasticityModel.h │ ├── RotatedLinear.cpp │ ├── SimpleShell.cpp │ ├── SimpleShell.h │ ├── Springs.cpp │ ├── Springs.h │ ├── StrainMeasure.cpp │ ├── StrainMeasure.h │ ├── StrainMeasureHex.cpp │ ├── StrainMeasureHex.h │ ├── SurfacePins.cpp │ ├── SurfacePins.h │ ├── __init__.py │ ├── force_test.py │ ├── forward.h │ ├── module.cpp │ ├── simple-shell.nb │ ├── test_cfl.py │ └── test_force.py ├── geometry │ ├── AnalyticImplicit.cpp │ ├── AnalyticImplicit.h │ ├── ArcSegment.cpp │ ├── ArcSegment.h │ ├── Bezier.cpp │ ├── Bezier.h │ ├── Box.cpp │ ├── Box.h │ ├── BoxScalar.cpp │ ├── BoxScalar.h │ ├── BoxTree.cpp │ ├── BoxTree.h │ ├── BoxVector.cpp │ ├── BoxVector.h │ ├── CMakeLists.txt │ ├── Capsule.h │ ├── Cylinder.cpp │ ├── Cylinder.h │ ├── FastRay.h │ ├── FrameImplicit.cpp │ ├── FrameImplicit.h │ ├── Implicit.cpp │ ├── Implicit.h │ ├── ParticleTree.cpp │ ├── ParticleTree.h │ ├── Plane.cpp │ ├── Plane.h │ ├── Ray.h │ ├── RayIntersection.h │ ├── Segment.cpp │ ├── Segment.h │ ├── SimplexTree.cpp │ ├── SimplexTree.h │ ├── Sphere.cpp │ ├── Sphere.h │ ├── ThickShell.cpp │ ├── ThickShell.h │ ├── Triangle2d.cpp │ ├── Triangle2d.h │ ├── Triangle3d.cpp │ ├── Triangle3d.h │ ├── __init__.py │ ├── arc_fitting.cpp │ ├── arc_fitting.h │ ├── clip_open_arcs.cpp │ ├── clip_open_arcs.h │ ├── extract_contours.cpp │ ├── extract_contours.h │ ├── forward.h │ ├── gen-platonic │ ├── join_fragments.cpp │ ├── join_fragments.h │ ├── mass_properties.cpp │ ├── mass_properties.h │ ├── module.cpp │ ├── offset_mesh.cpp │ ├── offset_mesh.h │ ├── platonic.cpp │ ├── platonic.h │ ├── platonic.py │ ├── polygon.cpp │ ├── polygon.h │ ├── prism-helper │ ├── simplify_arcs.cpp │ ├── simplify_arcs.h │ ├── surface_levelset.cpp │ ├── surface_levelset.h │ ├── surface_of_revolution.cpp │ ├── surface_of_revolution.h │ ├── test_box_tree.py │ ├── test_offset.py │ ├── test_platonic.py │ ├── test_shape.py │ ├── test_surface_levelset.py │ └── traverse.h ├── image │ ├── CMakeLists.txt │ ├── ExrFile.cpp │ ├── ExrFile.h │ ├── Image.cpp │ ├── Image.h │ ├── JpgFile.cpp │ ├── JpgFile.h │ ├── MovFile.cpp │ ├── MovFile.h │ ├── PngFile.cpp │ ├── PngFile.h │ ├── __init__.py │ ├── color_utils.cpp │ ├── color_utils.h │ ├── forward.h │ ├── module.cpp │ └── test_mov.py ├── math │ ├── CMakeLists.txt │ ├── Factorial.h │ ├── One.h │ ├── Zero.h │ ├── __init__.py │ ├── argmax.h │ ├── argmin.h │ ├── cbrt.h │ ├── choice.h │ ├── clamp.h │ ├── componentwise.h │ ├── constants.h │ ├── copysign.h │ ├── cube.h │ ├── cyclic_shift.h │ ├── fallback_sort.h │ ├── givens.h │ ├── hash.cpp │ ├── hash.h │ ├── integer_log.h │ ├── inverse.h │ ├── isfinite.h │ ├── isnan.h │ ├── lerp.h │ ├── max.h │ ├── maxabs.h │ ├── maxmag.h │ ├── mean.h │ ├── min.h │ ├── minabs.h │ ├── minmag.h │ ├── module.cpp │ ├── numeric_limits.cpp │ ├── optimal_sort.cpp │ ├── optimal_sort.h │ ├── popcount.h │ ├── pow.h │ ├── rint.h │ ├── robust.h │ ├── sign.h │ ├── signed_compare.h │ ├── small_sort.h │ ├── sqr.h │ ├── sse.cpp │ ├── sse.h │ ├── test_hypot.py │ ├── test_sort.py │ ├── test_sse.py │ ├── test_uint128.py │ ├── uint128.cpp │ ├── uint128.h │ └── wrap.h ├── mesh │ ├── CMakeLists.txt │ ├── ComponentData.cpp │ ├── ComponentData.h │ ├── HalfedgeGraph.cpp │ ├── HalfedgeGraph.h │ ├── HalfedgeMesh.cpp │ ├── HalfedgeMesh.h │ ├── PolygonSoup.cpp │ ├── PolygonSoup.h │ ├── SegmentSoup.cpp │ ├── SegmentSoup.h │ ├── TriangleMesh.cpp │ ├── TriangleMesh.h │ ├── TriangleSoup.cpp │ ├── TriangleSoup.h │ ├── TriangleSubdivision.cpp │ ├── TriangleSubdivision.h │ ├── TriangleTopology.cpp │ ├── TriangleTopology.h │ ├── __init__.py │ ├── decimate.cpp │ ├── decimate.h │ ├── forward.h │ ├── ids.cpp │ ├── ids.h │ ├── improve_mesh.cpp │ ├── improve_mesh.h │ ├── io.cpp │ ├── io.h │ ├── loop-helper │ ├── lower_hull.cpp │ ├── lower_hull.h │ ├── mesh_debug.cpp │ ├── mesh_debug.h │ ├── module.cpp │ ├── quadric.cpp │ ├── quadric.h │ ├── refine_mesh.cpp │ ├── refine_mesh.h │ ├── simplify.cpp │ ├── simplify.h │ ├── test_decimate.py │ ├── test_halfedge.py │ ├── test_io.py │ ├── test_lower_hull.py │ ├── test_mesh.py │ ├── triangulate.cpp │ └── triangulate.h ├── module.cpp ├── openmesh │ ├── CMakeLists.txt │ ├── COPYRIGHT │ ├── TriMesh.cpp │ ├── TriMesh.h │ ├── __init__.py │ ├── color_cast.h │ ├── config.h │ ├── curvature.cpp │ ├── curvature.h │ ├── decimate.cpp │ ├── decimate.h │ ├── floodfill.h │ ├── forward.h │ ├── module.cpp │ ├── test_trimesh.py │ ├── triangulator.cpp │ ├── triangulator.h │ ├── visualize.cpp │ └── visualize.h ├── python │ ├── Buffer.cpp │ ├── Buffer.h │ ├── CMakeLists.txt │ ├── Class.cpp │ ├── Class.h │ ├── ClassTest.cpp │ ├── ExceptionValue.cpp │ ├── ExceptionValue.h │ ├── Frozen.py │ ├── Object.cpp │ ├── Object.h │ ├── Ptr.h │ ├── PyDictAdaptor.h │ ├── Ref.cpp │ ├── Ref.h │ ├── __init__.py │ ├── cast.h │ ├── config.h │ ├── enum.h │ ├── exceptions.cpp │ ├── exceptions.h │ ├── forward.h │ ├── from_python.cpp │ ├── from_python.h │ ├── function.cpp │ ├── function.h │ ├── module.cpp │ ├── module.h │ ├── new.h │ ├── numpy-types.h │ ├── numpy.cpp │ ├── numpy.h │ ├── outer_wrapper.h │ ├── pyrange.h │ ├── repr.cpp │ ├── repr.h │ ├── stl.h │ ├── test_class.py │ ├── test_convert.py │ ├── test_frozen.py │ ├── to_python.h │ ├── try_convert.cpp │ ├── try_convert.h │ ├── utility.h │ ├── wrap.h │ ├── wrap_call.h │ ├── wrap_constructor.cpp │ ├── wrap_constructor.h │ ├── wrap_field.cpp │ ├── wrap_field.h │ ├── wrap_function.cpp │ ├── wrap_function.h │ ├── wrap_iter.h │ ├── wrap_method.cpp │ ├── wrap_method.h │ ├── wrap_property.cpp │ └── wrap_property.h ├── random │ ├── CMakeLists.txt │ ├── Random.cpp │ ├── Random.h │ ├── Sobol.cpp │ ├── Sobol.h │ ├── __init__.py │ ├── counter.cpp │ ├── counter.h │ ├── forward.h │ ├── module.cpp │ ├── permute.cpp │ ├── permute.h │ ├── random123 │ │ ├── README │ │ ├── array.h │ │ ├── features │ │ │ ├── clangfeatures.h │ │ │ ├── compilerfeatures.h │ │ │ ├── gccfeatures.h │ │ │ ├── iccfeatures.h │ │ │ ├── msvcfeatures.h │ │ │ ├── nvccfeatures.h │ │ │ ├── open64features.h │ │ │ ├── openclfeatures.h │ │ │ ├── sse.h │ │ │ └── sunprofeatures.h │ │ └── threefry.h │ ├── sobol-helper │ └── test_random.py ├── solver │ ├── CMakeLists.txt │ ├── __init__.py │ ├── brent.cpp │ ├── brent.h │ ├── module.cpp │ ├── nelder_mead.py │ ├── pattern_max.cpp │ ├── pattern_max.h │ ├── powell.cpp │ ├── powell.h │ ├── quadratic.h │ └── test_min.py ├── structure │ ├── CMakeLists.txt │ ├── Empty.h │ ├── Hashtable.h │ ├── Heap.cpp │ ├── Heap.h │ ├── OperationHash.h │ ├── Pair.h │ ├── Quad.h │ ├── Queue.h │ ├── Quintuple.h │ ├── Singleton.h │ ├── Stack.h │ ├── Triple.h │ ├── Tuple.cpp │ ├── Tuple.h │ ├── UnionFind.h │ ├── forward.h │ ├── module.cpp │ └── test_heap.py ├── svg │ ├── CMakeLists.txt │ ├── nanosvg │ │ ├── nanosvg.cpp │ │ └── nanosvg.h │ ├── svg_to_bezier.cpp │ ├── svg_to_bezier.h │ └── test_svg.py ├── utility │ ├── CMakeLists.txt │ ├── CloneArray.cpp │ ├── CloneArray.h │ ├── Cloneable.h │ ├── CopyConst.h │ ├── DebugPrint.cpp │ ├── DebugPrint.h │ ├── HasCheapCopy.h │ ├── Hasher.h │ ├── IRange.h │ ├── IdSet.h │ ├── Log.cpp │ ├── Log.h │ ├── Log.py │ ├── LogEntry.cpp │ ├── LogEntry.h │ ├── LogScope.cpp │ ├── LogScope.h │ ├── ProgressIndicator.cpp │ ├── ProgressIndicator.h │ ├── Protect.h │ ├── STATIC_ASSERT_SAME.h │ ├── SanitizeFunction.h │ ├── Unique.h │ ├── __init__.py │ ├── base64.cpp │ ├── base64.h │ ├── c_str.h │ ├── compose.h │ ├── config.h │ ├── const_cast.h │ ├── convert_case.h │ ├── curry.cpp │ ├── curry.h │ ├── debug.cpp │ ├── debug.h │ ├── endian.h │ ├── enumerate.h │ ├── equals.h │ ├── format.cpp │ ├── format.h │ ├── forward.h │ ├── from_string.h │ ├── function.h │ ├── interrupts.cpp │ ├── interrupts.h │ ├── json_conversion.py │ ├── macro_map.h │ ├── module.cpp │ ├── move.h │ ├── mpl.h │ ├── openmp.h │ ├── overload.h │ ├── pass.h │ ├── path.cpp │ ├── path.h │ ├── prioritize.h │ ├── process.cpp │ ├── process.h │ ├── range.h │ ├── remove_commas.h │ ├── resource.cpp │ ├── resource.h │ ├── rounding.h │ ├── smart_ptr.h │ ├── stl.h │ ├── str.h │ ├── stream.cpp │ ├── stream.h │ ├── test_misc.py │ ├── test_try.py │ ├── time.cpp │ ├── time.h │ ├── tr1.h │ ├── tryfile.py │ ├── type_traits.h │ ├── using.h │ └── validity.h ├── value │ ├── Action.cpp │ ├── Action.h │ ├── CMakeLists.txt │ ├── ChangeTracker.py │ ├── Compute.cpp │ ├── Compute.h │ ├── ConstValue.cpp │ ├── ConstValue.h │ ├── Listen.cpp │ ├── Listen.h │ ├── Prop.cpp │ ├── Prop.h │ ├── PropManager.cpp │ ├── PropManager.h │ ├── Value.cpp │ ├── Value.h │ ├── Worker.py │ ├── __init__.py │ ├── convert.h │ ├── error_value.h │ ├── extract.h │ ├── forward.h │ ├── link.h │ ├── module.cpp │ ├── parser.py │ ├── test_value.py │ └── test_worker.py └── vector │ ├── ArithmeticPolicy.h │ ├── CMakeLists.txt │ ├── DiagonalMatrix.h │ ├── DiagonalMatrix2x2.h │ ├── DiagonalMatrix3x3.h │ ├── Dot.h │ ├── Frame.cpp │ ├── Frame.h │ ├── Frame.py │ ├── Matrix.cpp │ ├── Matrix.h │ ├── Matrix.py │ ├── Matrix0x0.h │ ├── Matrix1x1.h │ ├── Matrix2x2.cpp │ ├── Matrix2x2.h │ ├── Matrix3x2.cpp │ ├── Matrix3x2.h │ ├── Matrix3x3.cpp │ ├── Matrix3x3.h │ ├── Matrix4x4.cpp │ ├── Matrix4x4.h │ ├── Quaternion.h │ ├── Register.cpp │ ├── Register.h │ ├── Rotation.cpp │ ├── Rotation.h │ ├── Rotation.py │ ├── ScalarPolicy.h │ ├── SolidMatrix.cpp │ ├── SolidMatrix.h │ ├── SparseMatrix.cpp │ ├── SparseMatrix.h │ ├── SymmetricMatrix.h │ ├── SymmetricMatrix2x2.h │ ├── SymmetricMatrix3x3.cpp │ ├── SymmetricMatrix3x3.h │ ├── TetrahedralGroup.cpp │ ├── TetrahedralGroup.h │ ├── Twist.h │ ├── UpperTriangularMatrix.h │ ├── UpperTriangularMatrix2x2.h │ ├── UpperTriangularMatrix3x3.h │ ├── Vector.cpp │ ├── Vector.h │ ├── Vector0d.h │ ├── Vector1d.h │ ├── Vector2d.h │ ├── Vector3d.h │ ├── Vector4d.h │ ├── VectorPolicy.h │ ├── __init__.py │ ├── blas.cpp │ ├── blas.h │ ├── complex.h │ ├── convert.h │ ├── forward.h │ ├── group-helper │ ├── group.cpp │ ├── group.h │ ├── magnitude.h │ ├── module.cpp │ ├── normalize.h │ ├── relative_error.h │ ├── test_frames.py │ ├── test_matrix.py │ ├── test_register.py │ ├── test_rotation.py │ └── test_vector.py ├── metaBuild.sh ├── metabuild_scripts ├── common_geode_build.sh ├── macos_clang_38.sh ├── macos_default.sh ├── ubuntu_1604_clang_35.sh ├── ubuntu_1604_clang_36.sh ├── ubuntu_1604_clang_37.sh ├── ubuntu_1604_clang_38.sh ├── ubuntu_1604_clang_39.sh ├── ubuntu_1604_gcc_474.sh ├── ubuntu_1604_gcc_541.sh └── ubuntu_1604_gcc_620.sh ├── requirements.txt ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pdf 3 | .DS_Store 4 | *~ 5 | \#* 6 | *\# 7 | *.orig 8 | *.sublime-project 9 | *.sublime-workspace 10 | *.vcxproj.user 11 | Debug*/ 12 | Release*/ 13 | /config.py 14 | .sconsign.dblite 15 | .sconf_temp 16 | config.log 17 | build 18 | dist 19 | *.egg-info 20 | *.so 21 | *.swp 22 | -------------------------------------------------------------------------------- /.priority: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /bin/fix-various: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | '''Fix the case of all C/C++ include statements''' 3 | 4 | import os 5 | import re 6 | import sys 7 | import fileinput 8 | 9 | def log(s): 10 | print>>sys.stderr, s 11 | 12 | include_pattern = re.compile(r'^#include\s+(["<])([\w/.]+)([">])\s*$') 13 | bases = [os.path.dirname(os.path.dirname(__file__))] 14 | 15 | def find(head,tail): 16 | head,tail = os.path.split(path) 17 | for base in bases: 18 | for f in os.listdir(os.path.join(base,head)): 19 | if f.lower()==tail.lower(): 20 | return f 21 | log("couldn't find '%s'"%path) 22 | return tail 23 | 24 | fixed = {'':''} 25 | def fix(path): 26 | try: 27 | return fixed[path] 28 | except KeyError: 29 | head,tail = os.path.split(path) 30 | tail = find(head,tail) 31 | fixed[path] = os.path.join(fix(head),tail) 32 | return fixed[path] 33 | 34 | for line in fileinput.input(inplace=1): 35 | # Fix case of includes 36 | m = include_pattern.match(line) 37 | if m: 38 | scope = m.group(1) 39 | path = m.group(2) 40 | if scope=='"': 41 | log('relative include: "%s"'%path) 42 | elif path.lower().startswith('other/'): 43 | line = '#include <%s>\n'%os.path.normpath(fix(path)) 44 | 45 | # Make sure all lines end with a newline 46 | if not line.endswith('\n'): 47 | line += '\n' 48 | print line, 49 | -------------------------------------------------------------------------------- /bin/symbol-counts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import re 5 | import sys 6 | import subprocess 7 | from collections import defaultdict 8 | import optparse 9 | 10 | usage = "usage: %prog [options...] [files...]" 11 | parser = optparse.OptionParser(usage) 12 | #parser.add_option('-s','--summary',action='store_true',help='summarize info about each file') 13 | options,files = parser.parse_args() 14 | 15 | counts = defaultdict(lambda:0) 16 | types = defaultdict(lambda:set()) 17 | 18 | symbol_pattern = re.compile(r'^(\d+) (\w) (.*)$') 19 | for file in files: 20 | for line in subprocess.Popen('gnm -gC -t d --defined-only'.split()+[file],stdout=subprocess.PIPE,stderr=subprocess.PIPE).stdout: 21 | m = symbol_pattern.match(line) 22 | if not m: 23 | print>>sys.stderr,'weird line:',line, 24 | sys.exit(1) 25 | s = m.group(3) 26 | counts[s] += 1 27 | types[s].add(m.group(2)) 28 | 29 | symbols = sorted(counts.keys(),key=lambda s:counts[s]) 30 | for s in symbols: 31 | print '%d %s %s'%(counts[s],''.join(types[s]),s) 32 | -------------------------------------------------------------------------------- /bin/trycat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import optparse 4 | from geode.utility import tryfile 5 | from numpy import * 6 | 7 | usage="usage: %prog [options] ..." 8 | parser=optparse.OptionParser(usage) 9 | parser.add_option('-s','--summary',action='store_true',help='print structure only') 10 | parser.add_option('-b','--boxes',action='store_true',help='print bounding boxes for arrays of vectors') 11 | parser.add_option('-l','--width',type=int,default=0,help='change line width for numpy printing') 12 | options,args = parser.parse_args() 13 | 14 | if options.width: 15 | set_printoptions(linewidth=options.width) 16 | 17 | def dump(indent,d): 18 | if isinstance(d,dict): 19 | for k,v in d.items(): 20 | print '%s%s'%(indent,k), 21 | if isinstance(v,ndarray): 22 | print ':', 23 | if v.ndim: print v.shape, 24 | print v.dtype, 25 | if options.boxes and v.ndim: 26 | if 2<=v.shape[-1]<=4: 27 | vb = v.reshape(-1,v.shape[-1]) 28 | print '%s-%s'%tuple('[%s]'%','.join(str(a) for a in e) for e in (vb.min(axis=0),vb.max(axis=0))), 29 | else: 30 | print '%s-%s'%(v.min(),v.max()) 31 | print 32 | dump(indent+' ',v) 33 | elif not options.summary: 34 | for s in str(d).split('\n'): 35 | print '%s%s'%(indent,s) 36 | 37 | for f in args: 38 | print '%s:'%f 39 | data = tryfile.read(f) 40 | dump(' ',data) 41 | -------------------------------------------------------------------------------- /geode.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=${prefix}/lib 3 | includedir=${prefix}/include 4 | 5 | Name: geode 6 | Description: Computational Geometry Library 7 | Version: 0.0.1 8 | Libs: -L${libdir} -lgeode 9 | Cflags: -I${includedir} 10 | -------------------------------------------------------------------------------- /geode/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import platform 4 | def is_windows(): 5 | return platform.system()=='Windows' 6 | 7 | # Import geode_wrap, possibly as geode_all on windows 8 | if is_windows(): 9 | from . import geode_all as geode_wrap 10 | from .geode_all import * 11 | else: 12 | from . import geode_wrap 13 | from .geode_wrap import * 14 | 15 | # py.test overrides AssertionError, so make sure C++ knows about it 16 | geode_wrap.redefine_assertion_error(AssertionError) 17 | 18 | # Import children 19 | from .utility import * 20 | from .array import * 21 | if has_exact(): 22 | from .exact import * 23 | from .geometry import * 24 | from .value import * 25 | from .vector import * 26 | from .mesh import * 27 | real = geode_wrap.real 28 | -------------------------------------------------------------------------------- /geode/array/ArrayAbs.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ArrayAbs 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template class ArrayAbs; 12 | template struct IsArray >:public mpl::true_{}; 13 | template struct HasCheapCopy >:public mpl::true_{}; 14 | 15 | template 16 | class ArrayAbs : public ArrayExpression,TArray> { 17 | typedef typename TArray::Element T; 18 | typedef typename mpl::if_,const TArray,const TArray&>::type TArrayView; 19 | public: 20 | typedef T Element; 21 | 22 | TArrayView array; 23 | 24 | explicit ArrayAbs(const TArray& array) 25 | : array(array) {} 26 | 27 | int size() const { 28 | return array.size(); 29 | } 30 | 31 | const T operator[](const int i) const { 32 | return abs(array[i]); 33 | } 34 | }; 35 | 36 | template static inline ArrayAbs abs(const ArrayBase& array) { 37 | return ArrayAbs(array.derived()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /geode/array/ArrayNegation.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ArrayNegation 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template class ArrayNegation; 11 | template struct IsArray >:public mpl::true_{}; 12 | template struct HasCheapCopy >:public mpl::true_{}; 13 | 14 | template 15 | class ArrayNegation : public ArrayExpression,TArray> { 16 | typedef typename TArray::Element T; 17 | typedef typename mpl::if_,const TArray,const TArray&>::type TArrayView; 18 | public: 19 | typedef T Element; 20 | 21 | TArrayView array; 22 | 23 | explicit ArrayNegation(const TArray& array) 24 | : array(array) {} 25 | 26 | int size() const { 27 | return array.size(); 28 | } 29 | 30 | const T operator[](const int i) const { 31 | return -array[i]; 32 | } 33 | }; 34 | 35 | template static inline ArrayNegation operator-(const ArrayBase& array) { 36 | return ArrayNegation(array.derived()); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /geode/array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SOURCES 2 | Array2d.cpp 3 | Array.cpp 4 | NdArray.cpp 5 | Nested.cpp 6 | permute.cpp 7 | RawArray.cpp 8 | stencil.cpp 9 | ) 10 | 11 | set(module_HEADERS 12 | alloca.h 13 | amap.h 14 | arange.h 15 | Array2d.h 16 | Array3d.h 17 | Array4d.h 18 | ArrayAbs.h 19 | ArrayBase.h 20 | ArrayDifference.h 21 | ArrayExpression.h 22 | Array.h 23 | ArrayIter.h 24 | ArrayLeftMultiple.h 25 | ArrayNdBase.h 26 | ArrayNegation.h 27 | ArrayPlusScalar.h 28 | ArrayProduct.h 29 | ArraySum.h 30 | ConstantMap.h 31 | convert.h 32 | Field.h 33 | forward.h 34 | IndirectArray.h 35 | NdArray.h 36 | NestedField.h 37 | Nested.h 38 | permute.h 39 | ProjectedArray.h 40 | RawArray.h 41 | RawField.h 42 | RawStack.h 43 | reversed.h 44 | SmallArray.h 45 | sort.h 46 | stencil.h 47 | Subarray.h 48 | UntypedArray.h 49 | view.h 50 | ) 51 | 52 | install_geode_headers(array ${module_HEADERS}) 53 | 54 | add_geode_module(array ${module_SOURCES}) 55 | -------------------------------------------------------------------------------- /geode/array/ConstantMap.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ConstantMap 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template struct IsArray >:public mpl::true_{}; 10 | template struct HasCheapCopy >:public mpl::true_{}; 11 | 12 | template 13 | class ConstantMap : public ArrayBase > { 14 | typedef T_ T; 15 | public: 16 | typedef T Element; 17 | private: 18 | int m; 19 | T constant; 20 | public: 21 | 22 | ConstantMap(const int m,const T constant) 23 | : m(m), constant(constant) 24 | {} 25 | 26 | int size() const { 27 | return m; 28 | } 29 | 30 | const T& operator[](const int i) const { 31 | assert(unsigned(i) static inline ConstantMap constant_map(int n,const T& constant) { 37 | return ConstantMap(n,constant); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /geode/array/NdArray.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class NdArray 3 | //##################################################################### 4 | #include 5 | namespace geode { 6 | 7 | NDARRAY_CONVERSIONS(uint8_t) 8 | NDARRAY_CONVERSIONS(int) 9 | NDARRAY_CONVERSIONS(long) 10 | NDARRAY_CONVERSIONS(long long) 11 | NDARRAY_CONVERSIONS(unsigned long) 12 | NDARRAY_CONVERSIONS(unsigned long long) 13 | NDARRAY_CONVERSIONS(float) 14 | NDARRAY_CONVERSIONS(double) 15 | NDARRAY_CONVERSIONS(Vector) 16 | NDARRAY_CONVERSIONS(Vector) 17 | 18 | } 19 | -------------------------------------------------------------------------------- /geode/array/RawStack.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class RawStack 3 | //##################################################################### 4 | // 5 | // Use a RawArray as a stack. Since RawArray can't resize, the stack must have been correctly 6 | // preallocated (this will be tested with assert). 7 | // 8 | //##################################################################### 9 | #pragma once 10 | 11 | #include 12 | namespace geode { 13 | 14 | template 15 | class RawStack { 16 | public: 17 | const RawArray data; 18 | int n; 19 | 20 | explicit RawStack(RawArray data) 21 | : data(data), n(0) {} 22 | 23 | int size() const { 24 | return n; 25 | } 26 | 27 | T& pop() { 28 | assert(n); 29 | return data[--n]; 30 | } 31 | 32 | void push(const T& v) { 33 | assert(data.valid(n)); 34 | data[n++] = v; 35 | } 36 | }; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /geode/array/alloca.h: -------------------------------------------------------------------------------- 1 | // Macro to stack allocate a RawArray 2 | #pragma once 3 | 4 | #include 5 | #ifdef _WIN32 6 | #include 7 | #define GEODE_ALLOCA _alloca 8 | #else 9 | #include 10 | #define GEODE_ALLOCA alloca 11 | #endif 12 | 13 | // GEODE_RAW_ALLOCA(count,Type) stack allocates an uninitialized buffer using alloca, and returns it as a RawArray. 14 | // IMPORTANT: On Windows, the size argument is evaluated twice, since there is no equivalent to gcc's 15 | // statement expressions. If the count argument must be evaluated once, *do not* use this macro. 16 | #ifdef __GNUC__ 17 | #define GEODE_RAW_ALLOCA(count,...) ({ \ 18 | const int _count = (count); \ 19 | ::geode::RawArray<__VA_ARGS__>(_count,(__VA_ARGS__*)GEODE_ALLOCA(sizeof(__VA_ARGS__)*_count)); }) 20 | #else // Fallback version that evaluates the count argument twice 21 | #define GEODE_RAW_ALLOCA(count,...) \ 22 | (::geode::RawArray<__VA_ARGS__>((count),(__VA_ARGS__*)GEODE_ALLOCA(sizeof(__VA_ARGS__)*(count)))) 23 | #endif 24 | -------------------------------------------------------------------------------- /geode/array/arange.h: -------------------------------------------------------------------------------- 1 | // An expression template equivalent of numpy's arange 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | template<> struct IsArray:public mpl::true_{}; 9 | template<> struct HasCheapCopy:public mpl::true_{}; 10 | 11 | class ARange : public ArrayExpression { 12 | public: 13 | typedef int Element; 14 | private: 15 | int m; 16 | public: 17 | 18 | explicit ARange(const int m) 19 | : m(m) 20 | {} 21 | 22 | int size() const { 23 | return m; 24 | } 25 | 26 | int operator[](const int i) const { 27 | assert(unsigned(i) 4 | #include 5 | namespace geode { 6 | 7 | void inplace_partial_permute(UntypedArray& x, RawArray perm, Array& work, const int block) { 8 | const int m = perm.size(); 9 | const int b_size = block*x.t_size(); 10 | GEODE_ASSERT(x.size()==block*m); 11 | const int space = m ? (perm.max()+1)*b_size : 0; 12 | work.resize(space); 13 | for (int i=0;i= 0) 16 | memcpy(work.data()+pi*b_size,x.data()+i*b_size,b_size); 17 | } 18 | x.resize(space/x.t_size()); 19 | memcpy(x.data(),work.data(),space); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/array/reversed.h: -------------------------------------------------------------------------------- 1 | // A expression template reversing an array 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | template class Reversed; 9 | template struct IsArray> : public mpl::true_{}; 10 | template struct HasCheapCopy> : public mpl::true_{}; 11 | 12 | template class Reversed : public ArrayExpression,TA> { 13 | typedef typename TA::Element T; 14 | typedef typename mpl::if_,const TA,const TA&>::type TArrayView; 15 | public: 16 | typedef T Element; 17 | 18 | TArrayView array; 19 | 20 | explicit Reversed(const TA& array) 21 | : array(array) {} 22 | 23 | int size() const { 24 | return array.size(); 25 | } 26 | 27 | auto operator[](const int i) const 28 | -> decltype(array[i]) { 29 | return array[array.size()-1-i]; 30 | } 31 | }; 32 | 33 | template static inline Reversed reversed(const ArrayBase& array) { 34 | return Reversed(array.derived()); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /geode/array/stencil.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template<> GEODE_DEFINE_TYPE(MaxStencil) 12 | template<> GEODE_DEFINE_TYPE(MaxStencil) 13 | template<> GEODE_DEFINE_TYPE(MaxStencil) 14 | template<> GEODE_DEFINE_TYPE(MaxStencil) 15 | 16 | } 17 | using namespace geode; 18 | 19 | void wrap_stencil() { 20 | typedef uint8_t T; 21 | typedef const function, Vector const &)> ftype; 22 | typedef void(*stencil_ftype)(ftype &, int, const Array); 23 | GEODE_FUNCTION_2(apply_stencil_uint8, static_cast(apply_stencil)); 24 | typedef MaxStencil Self; 25 | Class("MaxStencil_uint8") 26 | .GEODE_INIT(int) 27 | .GEODE_FIELD(r) 28 | .GEODE_CALL(const Array, Vector const &) 29 | ; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /geode/array/test_stencil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import absolute_import 4 | from geode import * 5 | 6 | def test_stencil(): 7 | for n in 7,11,19: 8 | for m in 5,9,13: 9 | for r in 1,2,3,10: 10 | x = m*ones((m,n),dtype=uint8)-arange(m,dtype=uint8)[:,None] 11 | xo = x[:,0].astype(int) 12 | if 0: 13 | print "before (m = %d, n = %d, r = %d): " % (m,n,r) 14 | print "x[:,0] =", x[:,0] 15 | apply_stencil_uint8(MaxStencil_uint8(r),r,x) 16 | if 0: 17 | print "after:" 18 | print "x[:,0] =", x[:,0] 19 | # Make sure the pattern makes sense 20 | diff = xo-x[:,0] 21 | i = arange(min(m,r+1)) 22 | assert all(diff[i]==-i) 23 | i = arange(r+1,m) 24 | assert all(diff[i]==-r) 25 | 26 | if __name__ == '__main__': 27 | test_stencil() 28 | -------------------------------------------------------------------------------- /geode/config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine GEODE_PYTHON 2 | #cmakedefine GEODE_LIBJPEG 3 | #cmakedefine GEODE_LIBPNG 4 | #cmakedefine GEODE_THREAD_SAFE true 5 | #cmakedefine __SSE__ 6 | #cmakedefine GEODE_GMP 7 | 8 | #include 9 | #include 10 | -------------------------------------------------------------------------------- /geode/exact/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SOURCES 2 | circle_csg.cpp 3 | circle_objects.cpp 4 | circle_offsets.cpp 5 | exact_circle_offsets.cpp 6 | circle_quantization.cpp 7 | collision.cpp 8 | constructions.cpp 9 | delaunay.cpp 10 | Exact.cpp 11 | ExactSegmentGraph.cpp 12 | Expansion.cpp 13 | Interval.cpp 14 | irreducible.cpp 15 | mesh_csg.cpp 16 | perturb.cpp 17 | PlanarArcGraph.cpp 18 | polygon_csg.cpp 19 | polynomial.cpp 20 | predicates.cpp 21 | simple_triangulate.cpp 22 | find_overlapping_offsets.cpp 23 | ) 24 | 25 | set(module_HEADERS 26 | circle_csg.h 27 | circle_enums.h 28 | circle_objects.h 29 | circle_offsets.h 30 | circle_quantization.h 31 | collision.h 32 | config.h 33 | constructions.h 34 | debug.h 35 | delaunay.h 36 | exact_circle_offsets.h 37 | exact-generated.h 38 | Exact.h 39 | ExactSegmentGraph.h 40 | Expansion.h 41 | find_overlapping_offsets.h 42 | forward.h 43 | Interval.h 44 | irreducible.h 45 | math.h 46 | mesh_csg.h 47 | perturb.h 48 | PlanarArcGraph.h 49 | polygon_csg.h 50 | polynomial.h 51 | predicates.h 52 | quantize.h 53 | scope.h 54 | simple_triangulate.h 55 | ) 56 | 57 | install_geode_headers(exact ${module_HEADERS}) 58 | 59 | add_geode_module(exact ${module_SOURCES}) 60 | -------------------------------------------------------------------------------- /geode/exact/circle_quantization.h: -------------------------------------------------------------------------------- 1 | // Robust constructive solid geometry for circular arc polygons in the plane 2 | #pragma once 3 | 4 | // These routines use algorithms almost identical to the actual polygon case, except using implicit 5 | // representations for arcs and different (much higher order) predicates to check topology. 6 | 7 | #include 8 | #include 9 | 10 | namespace geode { 11 | 12 | // Returns a center and radius for an exact circle that passes within constructed_arc_endpoint_error_bound() units of each quantized vertex and has approxamently the correct curvature 13 | GEODE_CORE_EXPORT Tuple, Quantized> construct_circle_center_and_radius(const Vector x0, const Vector x1, const real q); 14 | GEODE_CORE_EXPORT Quantized constructed_arc_endpoint_error_bound(); 15 | 16 | // Returns a quantizer padded to be able to approximate straight lines 17 | GEODE_CORE_EXPORT Quantizer make_arc_quantizer(const Box> arc_bounds); 18 | 19 | } // namespace geode 20 | -------------------------------------------------------------------------------- /geode/exact/constructions.h: -------------------------------------------------------------------------------- 1 | // Nearly exact geometric constructions 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // Construct the intersection of two segments, assuming they actually do intersect. 9 | // Due to an initial interval filter, the result differs from the true value by up to segment_segment_intersection_threshold. 10 | GEODE_CORE_EXPORT GEODE_PURE exact::Vec2 segment_segment_intersection(const exact::Perturbed2 a0, const exact::Perturbed2 a1, const exact::Perturbed2 b0, const exact::Perturbed2 b1); 11 | const int segment_segment_intersection_threshold = 100; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /geode/exact/find_overlapping_offsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | namespace geode { 4 | 5 | // Splits arcs into contiguous solid components and finds areas that are less than 'd' from two or more different components 6 | // If d is negative, components will be the holes instead 7 | GEODE_CORE_EXPORT Nested find_overlapping_offsets(const Nested arcs, const real d); 8 | 9 | 10 | } // namespace geode 11 | -------------------------------------------------------------------------------- /geode/exact/forward.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Forward declarations for circle data types 5 | namespace geode { 6 | typedef Perturbation Pb; 7 | 8 | template struct ExactCircle; 9 | template struct ExactHorizontal; 10 | template struct ExactArc; 11 | template struct ExactHorizontalArc; 12 | 13 | template struct IncidentCircle; 14 | template struct IncidentHorizontal; 15 | 16 | template struct CircleIntersectionKey; 17 | template struct CircleIntersection; 18 | template struct HorizontalIntersection; 19 | 20 | struct ApproxIntersection; 21 | 22 | // Shorthand typedefs 23 | typedef ExactCircle ExactCircleIm; 24 | typedef ExactCircle ExactCircleEx; 25 | } // namespace geode 26 | -------------------------------------------------------------------------------- /geode/exact/irreducible.h: -------------------------------------------------------------------------------- 1 | // Irreducibility testing for integer polynomials 2 | #pragma once 3 | 4 | // The efficiency of the symbolic perturbation core depends cubically on the degrees 5 | // of polynomial predicates, so it is useful to know whether said degrees can be reduced. 6 | // This code implements a randomized algorithm for checking irreducibility over Q. 7 | // To turn on checking for all predicates, flip the IRREDUCIBILITY flag. 8 | 9 | // Turn on to check whether all predicates and constructions are irreducible. 10 | #define IRREDUCIBLE 0 11 | 12 | #include 13 | namespace geode { 14 | 15 | // Check if a polynomial is irreducible, and bail if not. Reducible polynomials are 16 | // always correctly recognized as such, but some irreducible polynomials will be treated 17 | // as irreducible. Use with care. 18 | template void 19 | inexact_assert_irreducible(void(*const polynomial)(RawArray,RawArray,m>>), 20 | const int degree, const int inputs, const char* name); 21 | 22 | // Check if a degree 1 rational function is in lowest terms 23 | template void 24 | inexact_assert_lowest_terms(void(*const ratio)(RawArray,RawArray,m>>), 25 | const int degree, const int inputs, const int outputs, const char* name); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /geode/exact/mesh_csg.h: -------------------------------------------------------------------------------- 1 | // Robust constructive solid geometry for triangle meshes 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // If depth is this, faces at all depths are returned 9 | const int all_depths = std::numeric_limits::min(); 10 | 11 | // Resolve all intersections between triangle soups. 12 | GEODE_CORE_EXPORT Tuple,Array> 13 | split_soup(const TriangleSoup& faces, Array> X, const int depth); 14 | 15 | GEODE_CORE_EXPORT Tuple,Array> 16 | split_soup(const TriangleSoup& faces, Array> X, Array depth_weights, const int depth); 17 | 18 | GEODE_CORE_EXPORT Tuple,Array> 19 | exact_split_soup(const TriangleSoup& faces, Array X, const int depth); 20 | 21 | GEODE_CORE_EXPORT Tuple,Array> 22 | exact_split_soup(const TriangleSoup& faces, Array X, Array depth_weights, const int depth); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /geode/exact/module.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_exact() { 8 | GEODE_WRAP(interval) 9 | GEODE_WRAP(exact_exact) 10 | GEODE_WRAP(perturb) 11 | GEODE_WRAP(predicates) 12 | GEODE_WRAP(constructions) 13 | GEODE_WRAP(delaunay) 14 | GEODE_WRAP(polygon_csg) 15 | GEODE_WRAP(circle_csg) 16 | GEODE_WRAP(simple_triangulate) 17 | GEODE_WRAP(mesh_csg) 18 | GEODE_WRAP(polynomial) 19 | GEODE_WRAP(irreducible) 20 | typedef void(*void_fn_of_nested_circle_arcs)(Nested); 21 | GEODE_OVERLOADED_FUNCTION(void_fn_of_nested_circle_arcs,reverse_arcs) 22 | } 23 | -------------------------------------------------------------------------------- /geode/exact/scope.h: -------------------------------------------------------------------------------- 1 | // Conservative interval arithmetic. WARNING: Use with caution (see below) 2 | #pragma once 3 | 4 | // Modified from code by Tyson Brochu, 2011 5 | 6 | #include 7 | namespace geode { 8 | 9 | // All interval arithmetic must occur within an IntervalScope. Since the rounding 10 | // mode is local to each thread, care must be taken within multithreaded code. 11 | // 12 | // WARNING: On some compilers (clang!!) there is no way to make rounding mode changes 13 | // completely safe w.r.t. code motion. The most reliable method is to use IntervalScope 14 | // only at the top of functions, and to mark these functions with GEODE_NEVER_INLINE. 15 | // 16 | struct IntervalScope { 17 | const int previous_mode; 18 | 19 | IntervalScope() 20 | : previous_mode(fegetround()) { 21 | fesetround(FE_UPWARD); 22 | } 23 | 24 | ~IntervalScope() { 25 | fesetround(previous_mode); 26 | } 27 | 28 | private: 29 | // Noncopyable 30 | IntervalScope(const IntervalScope& rhs); 31 | IntervalScope& operator=(const IntervalScope& rhs); 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /geode/force/AnisotropicConstitutiveModel.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class AnisotropicConstitutiveModel 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template class AnisotropicConstitutiveModel : public ConstitutiveModel { 11 | public: 12 | typedef ConstitutiveModel Base; 13 | 14 | protected: 15 | AnisotropicConstitutiveModel(T failure_threshold=.1) 16 | : Base(failure_threshold) {} 17 | public: 18 | 19 | bool use_isotropic_stress_derivative() const { 20 | return false; 21 | } 22 | 23 | virtual T elastic_energy(const DiagonalMatrix& F,const Matrix& V,const int simplex) const=0; 24 | virtual Matrix P_From_Strain(const DiagonalMatrix& F,const Matrix& V,const T scale,const int simplex) const=0; 25 | virtual DiagonalizedStressDerivative stress_derivative(const DiagonalMatrix& F,const Matrix& V,const int simplex) const=0; 26 | virtual void update_position(const DiagonalMatrix& F,const Matrix& V,const int simplex){} 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /geode/force/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SOURCES 2 | AirPressure.cpp 3 | AxisPins.cpp 4 | BindingSprings.cpp 5 | ConstitutiveModel.cpp 6 | CubicHinges.cpp 7 | DiagonalizedIsotropicStressDerivative.cpp 8 | EtherDrag.cpp 9 | FiniteVolume.cpp 10 | Force.cpp 11 | Gravity.cpp 12 | LinearBendingElements.cpp 13 | LinearFiniteVolume.cpp 14 | LinearFiniteVolumeHex.cpp 15 | NeoHookean.cpp 16 | ParticleBindingSprings.cpp 17 | Pins.cpp 18 | PlasticityModel.cpp 19 | RotatedLinear.cpp 20 | SimpleShell.cpp 21 | Springs.cpp 22 | StrainMeasure.cpp 23 | StrainMeasureHex.cpp 24 | SurfacePins.cpp 25 | ) 26 | 27 | set(module_HEADERS 28 | AirPressure.h 29 | AnisotropicConstitutiveModel.h 30 | AxisPins.h 31 | BindingSprings.h 32 | ConstitutiveModel.h 33 | CubicHinges.h 34 | DiagonalizedIsotropicStressDerivative.h 35 | DiagonalizedStressDerivative.h 36 | EtherDrag.h 37 | FiniteVolume.h 38 | Force.h 39 | forward.h 40 | Gravity.h 41 | IsotropicConstitutiveModel.h 42 | LinearBendingElements.h 43 | LinearFiniteVolume.h 44 | LinearFiniteVolumeHex.h 45 | ParticleBindingSprings.h 46 | Pins.h 47 | PlasticityModel.h 48 | SimpleShell.h 49 | Springs.h 50 | StrainMeasure.h 51 | StrainMeasureHex.h 52 | SurfacePins.h 53 | ) 54 | 55 | install_geode_headers(force ${module_HEADERS}) 56 | 57 | add_geode_module(force ${module_SOURCES}) 58 | -------------------------------------------------------------------------------- /geode/force/ConstitutiveModel.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ConstitutiveModel 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | typedef real T; 11 | template<> GEODE_DEFINE_TYPE(ConstitutiveModel) 12 | template<> GEODE_DEFINE_TYPE(ConstitutiveModel) 13 | 14 | template ConstitutiveModel::ConstitutiveModel(T failure_threshold) 15 | : failure_threshold(failure_threshold) {} 16 | 17 | template ConstitutiveModel::~ConstitutiveModel() {} 18 | 19 | template DiagonalMatrix ConstitutiveModel::clamp_f(const DiagonalMatrix& F) const { 20 | return F.clamp_min(failure_threshold); 21 | } 22 | 23 | template class ConstitutiveModel; 24 | template class ConstitutiveModel; 25 | 26 | } 27 | using namespace geode; 28 | 29 | void wrap_constitutive_model() { 30 | {typedef ConstitutiveModel Self; 31 | Class("ConstitutiveModel2d");} 32 | 33 | {typedef ConstitutiveModel Self; 34 | Class("ConstitutiveModel3d");} 35 | } 36 | -------------------------------------------------------------------------------- /geode/force/Gravity.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Gravity 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template 12 | class Gravity : public Force { 13 | public: 14 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 15 | typedef Force Base; 16 | typedef typename TV::Scalar T; 17 | enum {m=TV::m}; 18 | 19 | TV gravity; 20 | private: 21 | Array mass; 22 | Array X; 23 | protected: 24 | Gravity(Array mass); 25 | public: 26 | ~Gravity(); 27 | 28 | void update_position(Array X,bool definite); 29 | void add_frequency_squared(RawArray frequency_squared) const; 30 | T elastic_energy() const; 31 | void add_elastic_force(RawArray F) const; 32 | void add_elastic_differential(RawArray dF,RawArray dX) const; 33 | void add_elastic_gradient_block_diagonal(RawArray > dFdX) const; 34 | T damping_energy(RawArray V) const; 35 | void add_damping_force(RawArray F,RawArray V) const; 36 | T strain_rate(RawArray V) const; 37 | 38 | int nodes() const; 39 | void structure(SolidMatrixStructure& structure) const; 40 | void add_elastic_gradient(SolidMatrix& matrix) const; 41 | void add_damping_gradient(SolidMatrix& matrix) const; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /geode/force/IsotropicConstitutiveModel.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class IsotropicConstitutiveModel 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template class IsotropicConstitutiveModel : public ConstitutiveModel { 10 | public: 11 | typedef ConstitutiveModel Base; 12 | 13 | protected: 14 | IsotropicConstitutiveModel(T failure_threshold=.1) 15 | : Base(failure_threshold) {} 16 | public: 17 | 18 | virtual T elastic_energy(const DiagonalMatrix& F,const int simplex) const=0; 19 | virtual DiagonalMatrix P_From_Strain(const DiagonalMatrix& F,const T scale,const int simplex) const=0; 20 | virtual void update_position(const DiagonalMatrix& F,const int simplex){} 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /geode/force/PlasticityModel.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class PlasticityModel 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | typedef real T; 10 | template<> GEODE_DEFINE_TYPE(PlasticityModel) 11 | template<> GEODE_DEFINE_TYPE(PlasticityModel) 12 | 13 | } 14 | using namespace geode; 15 | 16 | void wrap_plasticity_model() { 17 | {typedef PlasticityModel Self; 18 | Class("PlasticityModel2d");} 19 | 20 | {typedef PlasticityModel Self; 21 | Class("PlasticityModel3d");} 22 | } 23 | -------------------------------------------------------------------------------- /geode/force/PlasticityModel.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class PlasticityModel 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template class PlasticityModel : public Object { 10 | public: 11 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 12 | typedef Object Base; 13 | 14 | Array > Fp_inverse; 15 | 16 | PlasticityModel(const int elements) { 17 | Fp_inverse.exact_resize(elements); 18 | Fp_inverse.fill(SymmetricMatrix::identity_matrix()); 19 | } 20 | 21 | virtual ~PlasticityModel() {} 22 | 23 | virtual bool project_Fe(const DiagonalMatrix& Fe_trial,DiagonalMatrix& Fe_project) const=0; 24 | virtual void project_Fp(const int tetrahedron,const Matrix& Fp_trial)=0; 25 | }; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /geode/force/forward.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header Forces/Forward 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template class Springs; 10 | template class FiniteVolume; 11 | 12 | template class ConstitutiveModel; 13 | template class IsotropicConstitutiveModel; 14 | template class AnisotropicConstitutiveModel; 15 | template class DiagonalizedStressDerivative; 16 | template class DiagonalizedIsotropicStressDerivative; 17 | template class PlasticityModel; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /geode/force/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module Forces 3 | //##################################################################### 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_force() { 8 | GEODE_WRAP(Force) 9 | GEODE_WRAP(gravity) 10 | GEODE_WRAP(springs) 11 | GEODE_WRAP(finite_volume) 12 | GEODE_WRAP(strain_measure) 13 | GEODE_WRAP(strain_measure_hex) 14 | GEODE_WRAP(constitutive_model) 15 | GEODE_WRAP(neo_hookean) 16 | GEODE_WRAP(linear_bending) 17 | GEODE_WRAP(linear_finite_volume) 18 | GEODE_WRAP(linear_finite_volume_hex) 19 | GEODE_WRAP(cubic_hinges) 20 | GEODE_WRAP(ether_drag) 21 | GEODE_WRAP(air_pressure) 22 | GEODE_WRAP(simple_shell) 23 | GEODE_WRAP(pins) 24 | GEODE_WRAP(axis_pins) 25 | GEODE_WRAP(surface_pins) 26 | GEODE_WRAP(binding_springs) 27 | GEODE_WRAP(particle_binding_springs) 28 | } 29 | -------------------------------------------------------------------------------- /geode/force/test_cfl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division 4 | from numpy import * 5 | from geode import * 6 | from geode.force import * 7 | import unittest 8 | 9 | def dt(dx,stiffness,mass): 10 | mesh = SegmentSoup([[0,1]]) 11 | mass = array([1e10,mass],dtype=real) 12 | X = array([[0,0,0],[dx,0,0]],dtype=real) 13 | springs = edge_springs(mesh,mass,X,stiffness,1) 14 | sqr_frequency = zeros_like(mass) 15 | springs.add_frequency_squared(sqr_frequency) 16 | return 1/sqrt(sqr_frequency.max()) 17 | 18 | def test_cfl(): 19 | assert allclose(1/sqrt(2),dt(1,2,1)/dt(1,1,1)) 20 | assert allclose(2,dt(2,1,1)/dt(1,1,1)) 21 | assert allclose(1,dt(1,1,2)/dt(1,1,1)) 22 | 23 | if __name__=='__main__': 24 | test_cfl() 25 | -------------------------------------------------------------------------------- /geode/geometry/AnalyticImplicit.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class AnalyticImplicit 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template 10 | class AnalyticImplicit:public Implicit,public Shape 11 | { 12 | typedef real T; 13 | typedef typename Shape::VectorT TV; 14 | static_assert(is_same::value,""); 15 | public: 16 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 17 | typedef Implicit Base; 18 | 19 | protected: 20 | #ifdef GEODE_VARIADIC 21 | 22 | template 23 | AnalyticImplicit(const Args&... args) 24 | : Shape(args...) {} 25 | 26 | #else // Unpleasant nonvariadic versions 27 | 28 | template AnalyticImplicit(const A0& a0) : Shape(a0) {} 29 | template AnalyticImplicit(const A0& a0,const A1& a1) : Shape(a0,a1) {} 30 | template AnalyticImplicit(const A0& a0,const A1& a1,const A2& a2) : Shape(a0,a1,a2) {} 31 | 32 | #endif 33 | public: 34 | ~AnalyticImplicit(); 35 | 36 | T volume() const { 37 | return Shape::volume(); 38 | } 39 | 40 | virtual T phi(const TV& X) const; 41 | virtual TV normal(const TV& X) const; 42 | virtual TV surface(const TV& X) const; 43 | virtual bool lazy_inside(const TV& X) const; 44 | virtual Box bounding_box() const; 45 | virtual string repr() const; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /geode/geometry/Box.cpp: -------------------------------------------------------------------------------- 1 | // Class Box 2 | 3 | #include 4 | namespace geode { 5 | 6 | #ifndef _WIN32 7 | template Box bounding_box(const RawArray&); 8 | template Box> bounding_box(const RawArray>&); 9 | template Box> bounding_box(const RawArray>&); 10 | #endif 11 | 12 | } 13 | -------------------------------------------------------------------------------- /geode/geometry/BoxScalar.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Box 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | #ifdef GEODE_PYTHON 11 | 12 | template PyObject* to_python(const Box& self) { 13 | return to_python(tuple(self.min,self.max)); 14 | } 15 | 16 | template Box FromPython >::convert(PyObject* object) { 17 | const auto extents = from_python>(object); 18 | return Box(extents.x,extents.y); 19 | } 20 | 21 | #define INSTANTIATE(T) \ 22 | template GEODE_CORE_EXPORT PyObject* to_python(const Box&); \ 23 | template GEODE_CORE_EXPORT Box FromPython >::convert(PyObject*); 24 | INSTANTIATE(float) 25 | INSTANTIATE(double) 26 | INSTANTIATE(int) 27 | INSTANTIATE(int64_t) 28 | 29 | #endif 30 | 31 | } 32 | -------------------------------------------------------------------------------- /geode/geometry/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | AnalyticImplicit.cpp 3 | ArcSegment.cpp 4 | arc_fitting.cpp 5 | Bezier.cpp 6 | Box.cpp 7 | BoxScalar.cpp 8 | BoxTree.cpp 9 | BoxVector.cpp 10 | clip_open_arcs.cpp 11 | Cylinder.cpp 12 | extract_contours.cpp 13 | FrameImplicit.cpp 14 | Implicit.cpp 15 | join_fragments.cpp 16 | mass_properties.cpp 17 | offset_mesh.cpp 18 | ParticleTree.cpp 19 | Plane.cpp 20 | platonic.cpp 21 | polygon.cpp 22 | Segment.cpp 23 | SimplexTree.cpp 24 | simplify_arcs.cpp 25 | Sphere.cpp 26 | surface_levelset.cpp 27 | ThickShell.cpp 28 | Triangle2d.cpp 29 | Triangle3d.cpp 30 | ) 31 | 32 | set(module_HEADERS 33 | AnalyticImplicit.h 34 | ArcSegment.h 35 | arc_fitting.h 36 | Bezier.h 37 | Box.h 38 | BoxScalar.h 39 | BoxTree.h 40 | BoxVector.h 41 | Capsule.h 42 | clip_open_arcs.h 43 | Cylinder.h 44 | extract_contours.h 45 | FastRay.h 46 | forward.h 47 | FrameImplicit.h 48 | Implicit.h 49 | join_fragments.h 50 | mass_properties.h 51 | offset_mesh.h 52 | ParticleTree.h 53 | Plane.h 54 | platonic.h 55 | polygon.h 56 | Ray.h 57 | Segment.h 58 | SimplexTree.h 59 | simplify_arcs.h 60 | Sphere.h 61 | surface_levelset.h 62 | ThickShell.h 63 | traverse.h 64 | Triangle2d.h 65 | Triangle3d.h 66 | ) 67 | 68 | install_geode_headers(geometry ${module_HEADERS}) 69 | 70 | add_geode_module(geometry ${module_SRCS}) 71 | -------------------------------------------------------------------------------- /geode/geometry/Cylinder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | using std::ostream; 9 | 10 | class Cylinder 11 | { 12 | public: 13 | typedef real T; 14 | typedef Vector TV; 15 | enum {d = 3}; 16 | typedef TV VectorT; 17 | 18 | Plane base; // normal points through the cylinder 19 | T radius, height; 20 | 21 | Cylinder() 22 | : radius(1), height(1) {} 23 | 24 | Cylinder(const Plane& base, T radius, T height) 25 | : base(base), radius(radius), height(height) {} 26 | 27 | GEODE_CORE_EXPORT Cylinder(TV x0, TV x1, T radius); 28 | 29 | bool operator==(const Cylinder& other) const; 30 | TV normal(const TV& X) const; 31 | bool inside(const TV& X,const T half_thickness) const; 32 | bool lazy_inside(const TV& X) const; 33 | TV surface(const TV& X) const; 34 | T phi(const TV& X) const; 35 | T volume() const; 36 | Box bounding_box() const; 37 | Vector principal_curvatures(const TV& X) const; 38 | bool lazy_intersects(const Box& box) const; 39 | string repr() const; 40 | }; 41 | 42 | GEODE_CORE_EXPORT ostream& operator<<(ostream& output, const Cylinder& cylinder); 43 | GEODE_CORE_EXPORT PyObject* to_python(const Cylinder& cylinder); 44 | template<> struct FromPython{ GEODE_CORE_EXPORT static Cylinder convert(PyObject* object); }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /geode/geometry/FrameImplicit.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class FrameImplicit 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template 11 | class FrameImplicit:public Implicit 12 | { 13 | typedef typename TV::Scalar T; 14 | public: 15 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 16 | typedef Implicit Base; 17 | 18 | Frame frame; 19 | const Ref > object; 20 | 21 | FrameImplicit(Frame frame, const Implicit& object); 22 | virtual ~FrameImplicit(); 23 | 24 | virtual T phi(const TV& X) const; 25 | virtual TV normal(const TV& X) const; 26 | virtual TV surface(const TV& X) const; 27 | virtual bool lazy_inside(const TV& X) const; 28 | virtual Box bounding_box() const; 29 | virtual string repr() const; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /geode/geometry/Implicit.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Implicit 3 | //##################################################################### 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | typedef real T; 9 | template<> GEODE_DEFINE_TYPE(Implicit >) 10 | template<> GEODE_DEFINE_TYPE(Implicit >) 11 | template<> GEODE_DEFINE_TYPE(Implicit >) 12 | 13 | template const int Implicit::d; 14 | 15 | template Implicit:: 16 | Implicit() 17 | {} 18 | 19 | template Implicit:: 20 | ~Implicit() 21 | {} 22 | 23 | template class Implicit >; 24 | template class Implicit >; 25 | template class Implicit >; 26 | 27 | } 28 | using namespace geode; 29 | 30 | template static void wrap_helper() { 31 | typedef Vector TV; 32 | typedef Implicit Self; 33 | 34 | Class("Implicit") 35 | .GEODE_FIELD(d) 36 | .GEODE_METHOD(phi) 37 | .GEODE_METHOD(normal) 38 | .GEODE_METHOD(lazy_inside) 39 | .GEODE_METHOD(surface) 40 | .GEODE_METHOD(bounding_box) 41 | .GEODE_REPR() 42 | ; 43 | } 44 | 45 | void wrap_implicit() { 46 | wrap_helper<1>(); 47 | wrap_helper<2>(); 48 | wrap_helper<3>(); 49 | } 50 | -------------------------------------------------------------------------------- /geode/geometry/Implicit.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Implicit 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template 12 | class Implicit:public Object 13 | { 14 | typedef typename TV::Scalar T; 15 | public: 16 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 17 | static const int d = TV::m; 18 | 19 | Implicit(); 20 | virtual ~Implicit(); 21 | 22 | virtual T phi(const TV& X) const=0; 23 | virtual TV normal(const TV& X) const=0; 24 | virtual TV surface(const TV& X) const=0; 25 | virtual bool lazy_inside(const TV& X) const=0; 26 | virtual Box bounding_box() const=0; 27 | virtual string repr() const=0; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /geode/geometry/Sphere.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Sphere 3 | //##################################################################### 4 | #include 5 | namespace geode { 6 | 7 | // From Jack ritter: ftp://ftp-graphics.stanford.edu/pub/Graphics/RTNews/html/rtnews7b.html#art4 8 | template Sphere approximate_bounding_sphere(Array X) 9 | { 10 | typedef typename TV::Scalar T; 11 | if(!X.size()) return Sphere(TV(),0); 12 | Box box = bounding_box(X); 13 | Sphere sphere(box.center(),(T).5*box.sizes().max()); 14 | for(int i=0;isqr(sphere.radius)){ 18 | T distance=sqrt(sqr_distance); 19 | T shift=(T).5*(distance-sphere.radius); 20 | sphere.center+=shift/distance*DX; 21 | sphere.radius+=shift;}} 22 | return sphere; 23 | }; 24 | 25 | template Sphere > approximate_bounding_sphere(Array > X); 26 | } 27 | -------------------------------------------------------------------------------- /geode/geometry/ThickShell.h: -------------------------------------------------------------------------------- 1 | // Thickened shells generalizing capsules 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | class ThickShell : public Implicit> { 10 | public: 11 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 12 | typedef double T; 13 | typedef Vector TV; 14 | typedef Implicit Base; 15 | 16 | // Warning: The evaluation complexity is linear in the number of elements. 17 | // This class is intended for small numbers of triangles. 18 | const Array> tris; 19 | const Array> segs; 20 | const Array X; 21 | const Array radii; 22 | 23 | protected: 24 | ThickShell(const SegmentSoup& mesh, Array X, Array radii); 25 | ThickShell(const TriangleSoup& mesh, Array X, Array radii); 26 | ThickShell(Ref<> mesh, Array X, Array radii); 27 | public: 28 | ~ThickShell(); 29 | 30 | TV normal(const TV& X) const; 31 | bool lazy_inside(const TV& X) const; 32 | TV surface(const TV& X) const; 33 | T phi(const TV& X) const; 34 | Box bounding_box() const; 35 | string repr() const; 36 | 37 | private: 38 | Tuple phi_normal(const TV& X) const; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /geode/geometry/arc_fitting.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace geode { 6 | 7 | // Convert CircleArcs to polylines with at least enough samples to stay within max_deviation of original path 8 | Array discretize_arcs(const RawArray arc_points, const bool closed, const real max_deviation); 9 | Nested discretize_nested_arcs(const Nested arc_points, const bool closed, const real max_deviation); 10 | 11 | // Find the 'q' value for an ArcSegment or CircleArc with the given endpoints that would go through a target point 12 | // p0 is start of arc 13 | // p1 is end of arc 14 | // p3 is point on arc between start and end 15 | real fit_q(const Vec2 p0, const Vec2 p1, const Vec2 p3); 16 | // As fit_q, but returns the range of values that stay within the given error of p3 17 | Box fit_q_range(const Vec2 p0, const Vec2 p1, const Vec2 p3, const real allowed_error); 18 | 19 | // Fit CircleArcs to polylines/polygons at a specified tolerance 20 | // All endpoints will be within allowed_error of resulting arcs, error for interior of segments assumes endpoints were exactly on arc and thus can be slightly larger than allowed_error 21 | Array fit_arcs(const RawArray poly, const real allowed_error, const bool closed); 22 | Nested fit_polyarcs(const Nested polys, const real allowed_error, const bool closed); 23 | 24 | } // geode namespace 25 | -------------------------------------------------------------------------------- /geode/geometry/extract_contours.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace geode { 5 | 6 | // Read in raster data and convert to closed contours interpolating between samples 7 | // contour_edge_threshold: boundary is assumed to be at this value (i.g. 0.5 to a extract contour if input range is [0,1], or 0 if input range is [-1,1]) 8 | // default_sample_value: value used for border around 'samples' 9 | // This doesn't attempt to do any simplification on the result. Most users will want to pass results to fit_polyarcs (from geometry/arc_fitting.h) or a polygon simplification routine. (I don't know why it isn't exposed in the header, but there's a polygon_simplify in polygon.cpp) 10 | Nested extract_contours(const RawArray samples, const real contour_edge_threshold, const real default_sample_value); 11 | 12 | } // namespace geode 13 | -------------------------------------------------------------------------------- /geode/geometry/forward.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header Geometry/Forward 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template class Box; 11 | template class Segment; 12 | template class Triangle; 13 | template class Plane; 14 | template class RayIntersection; 15 | template class Sphere; 16 | class Cylinder; 17 | 18 | template class BoxTree; 19 | template class ParticleTree; 20 | template class SimplexTree; 21 | 22 | template class Implicit; 23 | 24 | template struct IsScalarBlock> : public IsScalarBlock{}; 25 | template struct is_packed_pod> : public is_packed_pod{}; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /geode/geometry/gen-platonic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division,print_function 4 | from numpy import * 5 | 6 | # Octahedron mesh 7 | X = tuple(tuple((-1)**j*(arange(3)==i)) for i in (0,1,2) for j in (0,1)) 8 | tris = [] 9 | for x in -1,1: 10 | for y in -1,1: 11 | for z in -1,1: 12 | a = asarray(((x,0,0),(0,y,0),(0,0,z))) 13 | i = [X.index(tuple(b)) for b in a] 14 | if dot(cross(a[1]-a[0],a[2]-a[0]),(x,y,z)) > 0: 15 | tris.append(i) 16 | else: 17 | tris.append(i[::-1]) 18 | print('static const IV tris[] = {%s};'%','.join('IV(%d,%d,%d)'%(i,j,k) for i,j,k in tris)) 19 | print('static const TV X[] = {%s};'%','.join('TV(%d,%d,%d)'%(x,y,z) for x,y,z in X)) 20 | -------------------------------------------------------------------------------- /geode/geometry/join_fragments.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace geode { 7 | 8 | // Greedily join closest endpoints together in a best-effort attempt to convert a set of open polylines to a set of closed contours 9 | Nested join_fragments(const Nested& fragments); 10 | Nested join_fragments(const Nested& fragments); 11 | 12 | } // namespace geode 13 | -------------------------------------------------------------------------------- /geode/geometry/mass_properties.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Mass properties of curves and surfaces 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template struct InertiaTensorPolicy; 12 | template struct InertiaTensorPolicy >{typedef Matrix WorldSpace;}; 13 | template struct InertiaTensorPolicy >{typedef T WorldSpace;}; 14 | template struct InertiaTensorPolicy >{typedef SymmetricMatrix WorldSpace;}; 15 | 16 | template struct MassProperties { 17 | typename TV::Scalar volume; 18 | TV center; 19 | typename InertiaTensorPolicy::WorldSpace inertia_tensor; 20 | 21 | MassProperties() 22 | :volume(),center(),inertia_tensor() {} 23 | }; 24 | 25 | template GEODE_CORE_EXPORT MassProperties mass_properties(RawArray > elements, RawArray X, bool filled); 26 | template GEODE_CORE_EXPORT Frame principal_frame(RawArray > elements, RawArray X, bool filled); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /geode/geometry/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module Geometry 3 | //##################################################################### 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_geometry() { 8 | GEODE_WRAP(arc_fitting) 9 | GEODE_WRAP(box_vector) 10 | GEODE_WRAP(polygon) 11 | GEODE_WRAP(implicit) 12 | GEODE_WRAP(frame_implicit) 13 | GEODE_WRAP(analytic_implicit) 14 | GEODE_WRAP(box_tree) 15 | GEODE_WRAP(particle_tree) 16 | GEODE_WRAP(simplex_tree) 17 | GEODE_WRAP(platonic) 18 | GEODE_WRAP(thick_shell) 19 | GEODE_WRAP(bezier) 20 | GEODE_WRAP(segment) 21 | GEODE_WRAP(surface_levelset) 22 | GEODE_WRAP(offset_mesh) 23 | } 24 | -------------------------------------------------------------------------------- /geode/geometry/platonic.h: -------------------------------------------------------------------------------- 1 | // Convenience functions for generating platonic solids 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace geode { 8 | 9 | GEODE_CORE_EXPORT Tuple,Array>> icosahedron_mesh(); 10 | GEODE_CORE_EXPORT Tuple,Array>> sphere_mesh(const int refinements, const Vector center=(Vector()), const real radius=1); 11 | 12 | GEODE_CORE_EXPORT Ref double_torus_mesh(); 13 | 14 | GEODE_CORE_EXPORT Tuple, Array>> cube_mesh(Vector const &min, Vector const &max); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /geode/geometry/simplify_arcs.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace geode { 4 | 5 | // This will collapse arc segments if it can ensure that no point moves by more than max_allowed_change. 6 | // It currently doesn't try to refit q values or combine arcs that are nearly 'co-circular' 7 | Array simplify_arcs(const RawArray input, const real max_allowed_change, const bool is_closed); 8 | Nested simplify_arcs(const Nested input, const real max_point_movement, const bool is_closed=false); 9 | 10 | } // namespace geode 11 | -------------------------------------------------------------------------------- /geode/geometry/surface_of_revolution.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | // Generates mesh by rotating profile_rz around z axis 8 | // Returns triangles and positions of vertices 9 | 10 | GEODE_CORE_EXPORT Tuple>,Array>> 11 | surface_of_revolution(const RawArray> profile_rz, const int sides); 12 | 13 | GEODE_CORE_EXPORT Tuple>,Array>> 14 | surface_of_revolution(const RawArray> profile_rz, const int sides); 15 | 16 | } // geode namespace 17 | -------------------------------------------------------------------------------- /geode/geometry/test_box_tree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division 4 | from geode import * 5 | from geode.geometry.platonic import * 6 | 7 | def test_box_tree(): 8 | random.seed(10098331) 9 | for n in 0,1,35,99,100,101,199,200,201: 10 | print 11 | x = random.randn(n,3).astype(real) 12 | tree = BoxTree(x,10) 13 | tree.check(x) 14 | 15 | def test_particle_tree(): 16 | random.seed(10098331) 17 | for n in 0,1,35,99,100,101,199,200,201: 18 | print 19 | X = random.randn(n,3).astype(real) 20 | tree = ParticleTree(X,10) 21 | tree.check(X) 22 | X[:] = random.randn(n,3).astype(real) 23 | tree.update() 24 | tree.check(X) 25 | 26 | def test_simplex_tree(): 27 | mesh,X = sphere_mesh(4) 28 | tree = SimplexTree(mesh,X,4) 29 | rays = 1000 30 | hits = ray_traversal_test(tree,rays,1e-6) 31 | print 'rays = %d, hits = %d'%(rays,hits) 32 | assert hits==642 33 | 34 | if __name__=='__main__': 35 | test_simplex_tree() 36 | -------------------------------------------------------------------------------- /geode/image/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | color_utils.cpp 3 | ExrFile.cpp 4 | Image.cpp 5 | JpgFile.cpp 6 | MovFile.cpp 7 | PngFile.cpp 8 | ) 9 | 10 | set(module_HEADERS 11 | color_utils.h 12 | ExrFile.h 13 | forward.h 14 | Image.h 15 | JpgFile.h 16 | MovFile.h 17 | PngFile.h 18 | ) 19 | 20 | install_geode_headers(image ${module_HEADERS}) 21 | 22 | add_geode_module(image ${module_SRCS}) 23 | -------------------------------------------------------------------------------- /geode/image/ExrFile.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ExrFile 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template class ExrFile { 12 | public: 13 | GEODE_CORE_EXPORT static Array,2> read(const std::string& filename); 14 | GEODE_CORE_EXPORT static void write(const std::string& filename,RawArray,2> image); 15 | GEODE_CORE_EXPORT static bool is_supported(); 16 | }; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /geode/image/JpgFile.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class JpgFile 3 | //##################################################################### 4 | // 5 | // Requires libjpeg (http://www.ijg.org/) 6 | // Note: Appears to give the error message 7 | // Jpeg parameter struct mismatch: library thinks size is 372, caller expects 376 8 | // with gcc which goes away if you don't use -malign-double 9 | //##################################################################### 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | namespace geode { 17 | 18 | template class JpgFile { 19 | public: 20 | GEODE_CORE_EXPORT static Array,2> read(const std::string& filename); 21 | GEODE_CORE_EXPORT static void write(const std::string& filename,RawArray,2> image); 22 | GEODE_CORE_EXPORT static bool is_supported(); 23 | }; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /geode/image/MovFile.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class MovFile 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | class QtAtom; 10 | 11 | class MovWriter : public Object { 12 | public: 13 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 14 | typedef Object Base; 15 | typedef real T; 16 | private: 17 | int frames_per_second; 18 | int width,height; 19 | FILE* fp; 20 | QtAtom* current_mov; 21 | Array sample_offsets; 22 | Array sample_lengths; 23 | 24 | protected: 25 | GEODE_CORE_EXPORT MovWriter(const std::string& filename,const int frames_per_second=24); 26 | public: 27 | GEODE_CORE_EXPORT ~MovWriter(); 28 | GEODE_CORE_EXPORT void add_frame(const Array,2>& image); 29 | GEODE_CORE_EXPORT void write_footer(); 30 | GEODE_CORE_EXPORT static bool enabled(); 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /geode/image/PngFile.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class PngFile (requires libpng) 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace geode { 11 | 12 | template class PngFile { 13 | public: 14 | GEODE_CORE_EXPORT static Array,2> read(const std::string& filename); 15 | GEODE_CORE_EXPORT static Array,2> read_alpha(const std::string& filename); 16 | GEODE_CORE_EXPORT static void write(const std::string& filename,RawArray,2> image); 17 | GEODE_CORE_EXPORT static void write(const std::string& filename,RawArray,2> image); 18 | GEODE_CORE_EXPORT static std::vector write_to_memory(RawArray,2> image); 19 | GEODE_CORE_EXPORT static std::vector write_to_memory(RawArray,2> image); 20 | GEODE_CORE_EXPORT static bool is_supported(); 21 | }; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /geode/image/__init__.py: -------------------------------------------------------------------------------- 1 | """image module""" 2 | 3 | from __future__ import (division,absolute_import) 4 | -------------------------------------------------------------------------------- /geode/image/color_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace geode { 5 | 6 | GEODE_CORE_EXPORT Vector hsv_to_rgb(Vector cin); 7 | GEODE_CORE_EXPORT Vector rgb_to_hsv(Vector const &cin); 8 | 9 | static inline Vector to_byte_color(Vector const &c, real alpha = 1) { 10 | return Vector(vec(255*c[0],255*c[1],255*c[2],255*alpha)); 11 | } 12 | 13 | static inline Vector wheel_color(real hue) { 14 | return hsv_to_rgb(Vector(hue,1,1)); 15 | } 16 | 17 | static inline Vector wheel_color(int i, int n) { 18 | return wheel_color(real(i)/n); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /geode/image/forward.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header image/forward 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template class Image; 9 | template class JpgFile; 10 | template class PngFile; 11 | template class MovFile; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /geode/image/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module Images 3 | //##################################################################### 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_image() { 8 | GEODE_WRAP(Image) 9 | GEODE_WRAP(mov) 10 | GEODE_WRAP(color_utils) 11 | } 12 | -------------------------------------------------------------------------------- /geode/image/test_mov.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division 4 | from geode import * 5 | 6 | if MovWriter.enabled(): 7 | def test_mov(filename=None): 8 | if not filename: 9 | file = named_tmpfile(suffix='.mov') 10 | filename = file.name 11 | mov = MovWriter(filename,24) 12 | w,h = 60,50 13 | y,x = meshgrid(arange(h),arange(w)) 14 | assert x.shape==y.shape==(w,h) 15 | x = (x-(w-1)/2)/h 16 | y = (y-(h-1)/2)/h 17 | for f in xrange(100): 18 | t = 3*f/100 19 | if t<1: 20 | c = (t,0,0) 21 | elif t<2: 22 | c = (2-t,t-1,0) 23 | else: 24 | c = (0,3-t,t-2) 25 | a = 4*pi*t/3 26 | image = c*(x*cos(a)+y*sin(a)+.5).reshape(w,h,1) 27 | mov.add_frame(image) 28 | 29 | if __name__=='__main__': 30 | test_mov('test.mov') 31 | -------------------------------------------------------------------------------- /geode/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | hash.cpp 3 | numeric_limits.cpp 4 | optimal_sort.cpp 5 | sse.cpp 6 | uint128.cpp 7 | ) 8 | 9 | set(module_HEADERS 10 | argmax.h 11 | argmin.h 12 | cbrt.h 13 | choice.h 14 | clamp.h 15 | componentwise.h 16 | constants.h 17 | copysign.h 18 | cube.h 19 | cyclic_shift.h 20 | Factorial.h 21 | fallback_sort.h 22 | givens.h 23 | hash.h 24 | integer_log.h 25 | inverse.h 26 | isfinite.h 27 | isnan.h 28 | lerp.h 29 | maxabs.h 30 | max.h 31 | maxmag.h 32 | mean.h 33 | minabs.h 34 | min.h 35 | minmag.h 36 | One.h 37 | optimal_sort.h 38 | popcount.h 39 | pow.h 40 | rint.h 41 | robust.h 42 | sign.h 43 | small_sort.h 44 | sqr.h 45 | sse.h 46 | uint128.h 47 | wrap.h 48 | Zero.h 49 | ) 50 | 51 | install_geode_headers(math ${module_HEADERS}) 52 | 53 | add_geode_module(math ${module_SRCS}) 54 | -------------------------------------------------------------------------------- /geode/math/Factorial.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Factorial 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template struct Factorial; 9 | 10 | template<> struct Factorial<0>{enum Workaround {value=1};}; 11 | 12 | template struct Factorial { 13 | static_assert(d<=12,"d! would overflow int"); 14 | enum Workaround {value=d*Factorial::value}; 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /geode/math/__init__.py: -------------------------------------------------------------------------------- 1 | """math module""" 2 | 3 | from __future__ import absolute_import 4 | 5 | speed_of_light = 2.99792458e8 # m/s 6 | plancks_constant = 6.6260755e-34 # J*s 7 | boltzmanns_constant = 1.380658e-23 # J/K 8 | ideal_gas_constant = 8.314472 # J/K/mol 9 | -------------------------------------------------------------------------------- /geode/math/argmax.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function argmax 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template static inline int argmax(const T a, const T b) { 9 | return a>=b?0:1; 10 | } 11 | 12 | template static inline int argmax(const T a, const T b, const T c) { 13 | if (a>=c) return argmax(a,b); 14 | return b>=c?1:2; 15 | } 16 | 17 | template inline int argmax(const T a, const T b, const T c, const T d) { 18 | T m = a; 19 | int r = 0; 20 | if (m static inline int argmin(const T a, const T b) { 9 | return b static inline int argmin(const T a, const T b, const T c) { 13 | if (a inline int argmin(const T a, const T b, const T c, const T d) { 18 | T m = a; 19 | int r = 0; 20 | if (m>b) {m=b;r=1;} 21 | if (m>c) {m=c;r=2;} 22 | if (m>d) r=3; 23 | return r; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /geode/math/cbrt.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function cbrt 3 | //##################################################################### 4 | // 5 | // Apparently cbrt is standard C but not standard C++. 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | #ifdef _WIN32 11 | #include 12 | #else 13 | #include 14 | #endif 15 | namespace geode { 16 | 17 | #ifdef _WIN32 18 | inline float cbrt(const float a){return ::pow(a,(float)(1/3.));} 19 | inline double cbrt(const double a){return ::pow(a,(double)(1/3.));} 20 | #else 21 | inline float cbrt(const float a){return ::cbrtf(a);} 22 | inline double cbrt(const double a){return ::cbrt(a);} 23 | #endif 24 | 25 | } 26 | -------------------------------------------------------------------------------- /geode/math/clamp.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function clamp 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template static inline T clamp(const T x, const T xmin, const T xmax) { 11 | if (x<=xmin) return xmin; 12 | else if (x>=xmax) return xmax; 13 | else return x; 14 | } 15 | 16 | template static inline T clamp_min(const T x, const T xmin) { 17 | return max(x,xmin); 18 | } 19 | 20 | template static inline T clamp_max(const T x, const T xmax) { 21 | return min(x,xmax); 22 | } 23 | 24 | template static inline bool in_bounds(const T x, const T xmin, const T xmax) { 25 | return xmin<=x && x<=xmax; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /geode/math/componentwise.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header componentwise 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template static inline T componentwise_min(const T& v1,const T& v2) { 11 | return T::componentwise_min(v1,v2); 12 | } 13 | 14 | static inline float componentwise_min(const float& v1,const float& v2) { 15 | return min(v1,v2); 16 | } 17 | 18 | static inline double componentwise_min(const double& v1,const double& v2) { 19 | return min(v1,v2); 20 | } 21 | 22 | template static inline T componentwise_min(const T& v1,const T& v2,const Rest&... rest) { 23 | return componentwise_min(v1,componentwise_min(v2,rest...)); 24 | } 25 | 26 | template static inline T componentwise_max(const T& v1,const T& v2) { 27 | return T::componentwise_max(v1,v2); 28 | } 29 | 30 | static inline float componentwise_max(const float& v1,const float& v2) { 31 | return max(v1,v2); 32 | } 33 | 34 | static inline double componentwise_max(const double& v1,const double& v2) { 35 | return max(v1,v2); 36 | } 37 | 38 | template static inline T componentwise_max(const T& v1,const T& v2,const Rest&... rest) { 39 | return componentwise_max(v1,componentwise_max(v2,rest...)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /geode/math/constants.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header constants 3 | //##################################################################### 4 | #pragma once 5 | #include 6 | 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | using std::numeric_limits; 12 | 13 | #ifdef _WIN32 14 | GEODE_CONSTEXPR_IF_NOT_MSVC double pi = 3.14159265358979323846; 15 | #else 16 | GEODE_CONSTEXPR_IF_NOT_MSVC double pi = M_PI; 17 | #endif 18 | GEODE_CONSTEXPR_IF_NOT_MSVC double half_pi = 0.5*pi; 19 | GEODE_CONSTEXPR_IF_NOT_MSVC double tau = 2*pi; 20 | GEODE_CONSTEXPR_IF_NOT_MSVC double speed_of_light = 2.99792458e8; // m/s 21 | GEODE_CONSTEXPR_IF_NOT_MSVC double plancks_constant = 6.6260755e-34; // J*s 22 | GEODE_CONSTEXPR_IF_NOT_MSVC double boltzmanns_constant = 1.380658e-23; // J/K 23 | GEODE_CONSTEXPR_IF_NOT_MSVC double ideal_gas_constant = 8.314472; // J/K/mol 24 | 25 | const double inf = numeric_limits::infinity(); 26 | 27 | template struct unit_sphere_size{static_assert(d<4,"");static const double value;}; 28 | template const double unit_sphere_size::value=d==0?0:d==1?2:d==2?pi:4*pi/3; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /geode/math/copysign.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function copysign 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | // The normal copysign functions don't always inline, so we make our own 10 | 11 | static inline float copysign(float mag, float sign) { 12 | uint32_t mask = 1<<31; 13 | union {float x;uint32_t i;} mag_, sign_; 14 | mag_.x = mag; 15 | sign_.x = sign; 16 | mag_.i = (mag_.i&~mask)|(sign_.i&mask); 17 | return mag_.x; 18 | } 19 | 20 | static inline double copysign(double mag, double sign) { 21 | uint64_t mask = (uint64_t)1<<63; 22 | union {double x;uint64_t i;} mag_, sign_; 23 | mag_.x = mag; 24 | sign_.x = sign; 25 | mag_.i = (mag_.i&~mask)|(sign_.i&mask); 26 | return mag_.x; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /geode/math/cube.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function cube 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template static inline auto cube(const T& a) 9 | -> decltype(a*a*a) { 10 | return a*a*a; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /geode/math/cyclic_shift.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Cyclic shifts 3 | //##################################################################### 4 | // 5 | // Cyclic shift 3 or 4 values 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | namespace geode { 11 | 12 | template inline void cyclic_shift(T& i, T& j, T& k) { 13 | T temp=k;k=j;j=i;i=temp; 14 | } 15 | 16 | template inline void cyclic_shift(T& i, T& j, T& k, T& l) { 17 | T temp=l;l=k;k=j;j=i;i=temp; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /geode/math/fallback_sort.h: -------------------------------------------------------------------------------- 1 | // Hybrid optimal / std sort 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // Sort an array with optimal sort for up to 4 elements, falling back to std::sort. 9 | // The cutoff is chosen because the advantage of optimal sort vs standard is 10 | // 48%, 16%, 18% for 2, 3, and 4 elements, then falls off to < 5% for 5-7 elements. 11 | template static inline void fallback_sort(TA& array, const Less& less) { 12 | const int n = int(array.size()); 13 | #define L() 14 | #define C(i,j) { \ 15 | auto &a = array[i], &b = array[j]; \ 16 | if (less(b,a)) swap(a,b); } 17 | switch (n) { 18 | case 0: case 1: break; 19 | case 2: GEODE_SORT_NETWORK(2,C,L); break; 20 | case 3: GEODE_SORT_NETWORK(3,C,L); break; 21 | case 4: GEODE_SORT_NETWORK(4,C,L); break; 22 | default: std::sort(array.begin(),array.end(),less); 23 | } 24 | #undef L 25 | #undef C 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /geode/math/givens.h: -------------------------------------------------------------------------------- 1 | // Givens rotations 2 | #pragma once 3 | 4 | #include 5 | namespace geode { 6 | 7 | // Compute a Givens rotation stored as a (cos,sin) pair, applying the rotation to the arguments in the process. 8 | template static inline Vector givens_and_apply(T& x, T& y) { 9 | const T s = sqrt(x*x+y*y); 10 | const auto g = s ? Vector(x,y)/s 11 | : Vector(1,0); 12 | x = s; 13 | y = 0; 14 | return g; 15 | } 16 | 17 | template static inline void givens_apply(const Vector& g, T& x, T& y) { 18 | T tx = g.x*x+g.y*y; 19 | y = g.x*y-g.y*x; 20 | x = tx; 21 | } 22 | 23 | template static inline void givens_unapply(const Vector& g, T& x, T& y) { 24 | T tx = g.x*x-g.y*y; 25 | y = g.x*y+g.y*x; 26 | x = tx; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /geode/math/hash.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function hash 3 | //##################################################################### 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | static Hash hash_string(size_t size,const char* s) { 9 | // TODO: process data in 64 bit blocks 10 | return hash_array(RawArray((int)size,s)); 11 | } 12 | 13 | Hash hash_reduce(const string& s) { 14 | return hash_string(s.size(),s.c_str()); 15 | } 16 | 17 | Hash hash_reduce(const char* s) { 18 | return hash_string(strlen(s),s); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /geode/math/inverse.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function inverse 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace geode { 11 | 12 | using ::std::abs; 13 | 14 | template static inline auto inverse(const T& x) 15 | -> typename disable_if,decltype(x.inverse())>::type { 16 | return x.inverse(); 17 | } 18 | 19 | static inline float inverse(const float x) { 20 | assert(abs(x)>=FLT_MIN); 21 | return 1/x; 22 | } 23 | 24 | static inline double inverse(const double x) { 25 | assert(abs(x)>=DBL_MIN); 26 | return 1/x; 27 | } 28 | 29 | template struct IntInverse { 30 | I a; 31 | IntInverse(I a) : a(a) {} 32 | }; 33 | 34 | template static inline typename enable_if,IntInverse>::type inverse(const I x) { 35 | assert(x!=0); 36 | return IntInverse(x); 37 | } 38 | 39 | template static inline I operator*(const I x, const IntInverse y) { 40 | return x/y.a; 41 | } 42 | 43 | template inline I& operator*=(I& x, const IntInverse y) { 44 | return x/=y.a; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /geode/math/isfinite.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace geode { 5 | 6 | #ifndef __GNUC__ 7 | 8 | template static inline bool isfinite(T x) { 9 | return _finite(x)!=0; 10 | } 11 | 12 | #else 13 | 14 | #undef isfinite 15 | using std::isfinite; 16 | 17 | #endif 18 | } 19 | -------------------------------------------------------------------------------- /geode/math/isnan.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function isnan 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | #ifndef __GNUC__ 10 | 11 | template static inline bool isnan(T x) { 12 | return _isnan(x)!=0; 13 | } 14 | 15 | #else 16 | 17 | using std::isnan; 18 | 19 | #endif 20 | } 21 | -------------------------------------------------------------------------------- /geode/math/lerp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace geode { 5 | 6 | template 7 | inline T lerp(real a, T const &x, T const &y) { 8 | return (1 - a) * x + a * y; 9 | } 10 | 11 | template 12 | inline T lerp(real a, real min, real max, T const &x, T const &y) { 13 | a = (a-min)/(max-min); 14 | return lerp(a, x, y); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /geode/math/maxmag.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function maxmag 3 | //##################################################################### 4 | // 5 | // finds the maximum value in magnitude and returns it with the sign 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | #include 11 | namespace geode { 12 | 13 | using std::abs; 14 | 15 | template inline T maxmag(const T a,const T b) { 16 | return abs(a)>abs(b)?a:b; 17 | } 18 | 19 | template inline T maxmag(const T a,const T b,const T c) { 20 | return maxmag(a,maxmag(b,c)); 21 | } 22 | 23 | template inline T maxmag(const T a,const T b,const T c,const T d) { 24 | return maxmag(a,maxmag(b,c,d)); 25 | } 26 | 27 | template inline T maxmag(const T a,const T b,const T c,const T d,const T e) { 28 | return maxmag(a,maxmag(b,c,d,e)); 29 | } 30 | 31 | template inline T maxmag(const T a,const T b,const T c,const T d,const T e,const T f) { 32 | return maxmag(a,maxmag(b,c,d,e,f)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /geode/math/mean.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function mean 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template inline const TV& mean(const TV& x) { 10 | return x; 11 | } 12 | 13 | template inline TV mean(const TV& x, const TV& y) { 14 | return typename ScalarPolicy::type(.5)*(x+y); 15 | } 16 | 17 | template inline TV mean(const TV& x, const TV& y, const TV& z) { 18 | return typename ScalarPolicy::type(1./3)*(x+y+z); 19 | } 20 | 21 | template inline TV mean(const TV& x, const TV& y, const TV& z, const TV& w) { 22 | return typename ScalarPolicy::type(.25)*(x+y+z+w); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /geode/math/minabs.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function minabs 3 | //##################################################################### 4 | // 5 | // finds the minimum absolute value 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | #include 11 | #include 12 | namespace geode { 13 | 14 | // a should already be nonnegative 15 | template static inline T minabs_incremental(const T a,const T b) { 16 | return min(a,abs(b)); 17 | } 18 | 19 | template static inline T minabs(const T a,const T b) { 20 | return min(abs(a),abs(b)); 21 | } 22 | 23 | template static inline T minabs(const T a,const T b,const T c) { 24 | return minabs_incremental(minabs(a,b),c); 25 | } 26 | 27 | template static inline T minabs(const T a,const T b,const T c,const T d) { 28 | return min(minabs(a,b),minabs(c,d)); 29 | } 30 | 31 | template static inline T minabs(const T a,const T b,const T c,const T d,const T e) { 32 | return minabs_incremental(minabs(a,b,c,d),e); 33 | } 34 | 35 | template static inline T minabs(const T a,const T b,const T c,const T d,const T e,const T f) { 36 | return min(minabs(a,b,c,d),minabs(e,f)); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /geode/math/minmag.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function minmag 3 | //##################################################################### 4 | // 5 | // finds the minimum value in magnitude and returns it with the sign 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | namespace geode { 11 | 12 | template static inline T minmag(const T a,const T b) { 13 | return abs(a) static inline T minmag(const T a,const T b,const T c) { 17 | return minmag(a,minmag(b,c)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /geode/math/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module math 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | // In some configurations, Python.h will attempt to redefine hypot as _hypot 10 | // This helps test that we got a hypot function that works 11 | static real geode_test_hypot(const real a, const real b) { 12 | using namespace std; 13 | return hypot(a,b); 14 | } 15 | } // namespace geode 16 | 17 | using namespace geode; 18 | 19 | void wrap_math() { 20 | GEODE_WRAP(uint128) 21 | GEODE_WRAP(numeric_limits) 22 | GEODE_WRAP(optimal_sort) 23 | GEODE_WRAP(sse) 24 | GEODE_FUNCTION(geode_test_hypot) 25 | GEODE_FUNCTION_2(integer_log,static_cast(integer_log)) 26 | GEODE_FUNCTION_2(popcount,static_cast(popcount)) 27 | GEODE_FUNCTION_2(min_bit,static_cast(min_bit)) 28 | } 29 | -------------------------------------------------------------------------------- /geode/math/popcount.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function popcount 3 | //##################################################################### 4 | #pragma once 5 | #include 6 | #include 7 | #ifdef _WIN32 8 | #include 9 | #endif 10 | namespace geode { 11 | 12 | #ifdef __GNUC__ 13 | 14 | static inline int popcount(uint16_t n) { 15 | return __builtin_popcount(n); 16 | } 17 | 18 | static inline int popcount(uint32_t n) { 19 | static_assert(sizeof(int)==4,""); 20 | return __builtin_popcount(n); 21 | } 22 | 23 | static inline int popcount(uint64_t n) { 24 | #if __SIZEOF_LONG__ == 8 25 | static_assert(sizeof(long)==8,""); 26 | return __builtin_popcountl(n); 27 | #elif __SIZEOF_LONG_LONG__ == 8 28 | static_assert(sizeof(long long)==8,""); 29 | return __builtin_popcountll(n); 30 | #else 31 | #error "Can't deduce __builtin_popcount for uint64_t" 32 | #endif 33 | } 34 | 35 | #else 36 | 37 | static inline int popcount(uint16_t n) { 38 | return __popcnt16(n); 39 | } 40 | 41 | static inline int popcount(uint32_t n) { 42 | static_assert(sizeof(int)==4,""); 43 | return __popcnt(n); 44 | } 45 | 46 | static inline int popcount(uint64_t n) { 47 | #ifdef _WIN64 48 | return (int)__popcnt64(n); 49 | #else 50 | return __popcnt(uint32_t(n>>32))+__popcnt(uint32_t(n)); 51 | #endif 52 | } 53 | 54 | #endif 55 | 56 | } 57 | -------------------------------------------------------------------------------- /geode/math/rint.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function rint 3 | //##################################################################### 4 | #pragma once 5 | 6 | #ifdef _WIN32 7 | #include 8 | #else 9 | #include 10 | #endif 11 | namespace geode { 12 | 13 | #ifdef _WIN32 14 | inline float rint(const float x){return floorf(x+(x>0?.5f:-.5f));} 15 | inline double rint(const double x){return floor(x+(x>0?.5:-.5));} 16 | #else 17 | inline float rint(const float x){return ::rintf(x);} 18 | inline double rint(const double x){return ::rint(x);} 19 | #endif 20 | 21 | } 22 | -------------------------------------------------------------------------------- /geode/math/sign.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function sign 3 | //##################################################################### 4 | // 5 | // finds the sign as +1, -1, or 0 6 | // 7 | //##################################################################### 8 | #pragma once 9 | 10 | namespace geode { 11 | 12 | template static inline T sign(const T a) { 13 | if (a>0) return 1; 14 | else if (a<0) return -1; 15 | else return 0; 16 | } 17 | 18 | template static inline T sign_nonzero(const T a) { 19 | return a>=0?1:-1; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/math/sqr.h: -------------------------------------------------------------------------------- 1 | // Square a number 2 | #pragma once 3 | 4 | #include 5 | namespace geode { 6 | 7 | template static inline auto sqr(const T& a) 8 | -> decltype(a*a) { 9 | return a*a; 10 | } 11 | 12 | // A monotonic version of sqr 13 | template static inline auto sign_sqr(const T& a) 14 | -> decltype(a*a) { 15 | return copysign(a*a,a); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /geode/math/sse.cpp: -------------------------------------------------------------------------------- 1 | // SSE tests 2 | 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | static bool geode_sse_enabled() { 8 | #ifdef GEODE_SSE 9 | return true; 10 | #else 11 | return false; 12 | #endif 13 | } 14 | 15 | #ifdef GEODE_SSE 16 | static Vector sse_pack_unpack(const Vector a) { 17 | return unpack(pack(a.x,a.y)); 18 | } 19 | #endif 20 | 21 | } 22 | using namespace geode; 23 | 24 | void wrap_sse() { 25 | GEODE_FUNCTION(geode_sse_enabled) 26 | #ifdef GEODE_SSE 27 | GEODE_FUNCTION(sse_pack_unpack) 28 | #endif 29 | } 30 | -------------------------------------------------------------------------------- /geode/math/test_hypot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division,print_function 4 | from geode import * 5 | 6 | def test_hypot(): 7 | # On some platforms Python.h will try to #define hypot as _hypot 8 | # Since some platforms define hypot as: 9 | # double hypot(double a, double b) { return _hypot(a,b); } 10 | # As a result calling hypot overflow the stack 11 | # geode/python/config.h tries to ensure we still have a hypot function but could also break things 12 | # We just make sure we can call hypot without a stack overflow: 13 | assert geode_test_hypot(1.,0.) == 1. 14 | 15 | if __name__=='__main__': 16 | test_hypot() 17 | -------------------------------------------------------------------------------- /geode/math/test_sort.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division,print_function 4 | from geode import * 5 | 6 | def test_optimal_sort(): 7 | optimal_sort_test() 8 | 9 | if __name__=='__main__': 10 | test_optimal_sort() 11 | -------------------------------------------------------------------------------- /geode/math/test_sse.py: -------------------------------------------------------------------------------- 1 | from geode import * 2 | from numpy import * 3 | 4 | def test_sse(): 5 | if not geode_sse_enabled(): 6 | return 7 | random.seed(3871) 8 | for i in xrange(10): 9 | x = random.randn(2) 10 | assert all(x==sse_pack_unpack(x)) 11 | -------------------------------------------------------------------------------- /geode/math/test_uint128.py: -------------------------------------------------------------------------------- 1 | from geode import * 2 | from numpy import * 3 | 4 | def test_uint128(): 5 | try: 6 | uint128_test(1<<128,0) 7 | except OverflowError: 8 | pass 9 | try: 10 | uint128_test(-1,0) 11 | except OverflowError: 12 | pass 13 | m64 = (1<<64)-1 14 | m128 = (1<<128)-1 15 | for i in xrange(100): 16 | x = threefry(0,i) 17 | y = threefry(1,i) 18 | r = uint128_test(x,y) 19 | assert r[0]==(-7)&m64 20 | assert r[1]==(-7)&m128 21 | assert r[2]==x 22 | assert r[3]==(x+y)&m128 23 | assert r[4]==(x-y)&m128 24 | assert r[5]==(x*y)&m128 25 | assert r[6]==(x<<5)&m128 26 | assert r[7]==x>>7 27 | for x in 0,19731,74599465401539225308381206871: 28 | assert uint128_str_test(x)=='0x%x'%x 29 | -------------------------------------------------------------------------------- /geode/math/wrap.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function wrap 3 | //##################################################################### 4 | // 5 | // wrap(i,n) adds a multiple of n to i to bring it into the set [0;n) 6 | // i + k*n is in [0,n) 7 | // 8 | //##################################################################### 9 | #pragma once 10 | 11 | #include 12 | #include 13 | namespace geode { 14 | 15 | using std::fmod; 16 | using std::abs; 17 | 18 | static inline int wrap(const int i, const int n) { 19 | assert(n > 0); 20 | int r = i % n; 21 | return r >= 0 ? r : r + n; 22 | } 23 | 24 | static inline int wrap(const int i, const int lower, const int upper) { 25 | int r = i-lower % (upper-lower); 26 | return r >= 0 ? r+lower : r+upper; 27 | } 28 | 29 | static inline float wrap(const float value, const float lower, const float upper) { 30 | float r = fmod(value-lower,upper-lower); 31 | return r<0?r+upper:r+lower; 32 | } 33 | 34 | static inline double wrap(const double value,const double lower,const double upper) { 35 | double r = fmod(value-lower,upper-lower); 36 | return r<0?r+upper:r+lower; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /geode/mesh/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | ComponentData.cpp 3 | decimate.cpp 4 | simplify.cpp 5 | HalfedgeGraph.cpp 6 | HalfedgeMesh.cpp 7 | ids.cpp 8 | improve_mesh.cpp 9 | io.cpp 10 | lower_hull.cpp 11 | mesh_debug.cpp 12 | module.cpp 13 | PolygonSoup.cpp 14 | quadric.cpp 15 | refine_mesh.cpp 16 | SegmentSoup.cpp 17 | TriangleMesh.cpp 18 | TriangleSoup.cpp 19 | TriangleSubdivision.cpp 20 | TriangleTopology.cpp 21 | triangulate.cpp 22 | ) 23 | 24 | set(module_HEADERS 25 | ComponentData.h 26 | decimate.h 27 | simplify.h 28 | forward.h 29 | HalfedgeGraph.h 30 | HalfedgeMesh.h 31 | ids.h 32 | improve_mesh.h 33 | io.h 34 | lower_hull.h 35 | mesh_debug.h 36 | PolygonSoup.h 37 | quadric.h 38 | refine_mesh.h 39 | SegmentSoup.h 40 | TriangleMesh.h 41 | TriangleSoup.h 42 | TriangleSubdivision.h 43 | TriangleTopology.h 44 | triangulate.h 45 | ) 46 | 47 | install_geode_headers(mesh ${module_HEADERS}) 48 | 49 | add_geode_module(mesh ${module_SRCS}) 50 | -------------------------------------------------------------------------------- /geode/mesh/forward.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header mesh/forward 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | class PolygonSoup; 10 | class SegmentSoup; 11 | class TriangleSoup; 12 | class HalfedgeMesh; 13 | class HalfedgeGraph; 14 | class TriangleMesh; 15 | class TriangleTopology; 16 | class TriangleSubdivision; 17 | 18 | template struct SimplexMesh; 19 | template<> struct SimplexMesh<1>{typedef SegmentSoup type;}; 20 | template<> struct SimplexMesh<2>{typedef TriangleSoup type;}; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/mesh/improve_mesh.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace geode { 4 | 5 | bool improve_mesh_inplace(MutableTriangleTopology &mesh, 6 | Field, VertexId> const &pos, 7 | ImproveOptions const &o) { 8 | auto Q = [](Triangle> const &t) { return t.quality(); }; 9 | auto EL = [](VertexId, VertexId) { return false; }; 10 | auto VL = [](VertexId) { return false; }; 11 | 12 | return improve_mesh_inplace(mesh, pos, o, EL, VL, Q); 13 | } 14 | 15 | // positions are assumed to be at default location 16 | Ref improve_mesh(MutableTriangleTopology const &mesh, real min_quality, real max_distance, real max_silhouette_distance, real min_normal_dot, int max_iter, real min_relevant_area, real min_quality_improvement) { 17 | FieldId,VertexId> posid(vertex_position_id); 18 | Ref copy = mesh.copy(); 19 | improve_mesh_inplace(copy, copy->field(posid), ImproveOptions(min_quality, max_distance, max_silhouette_distance, min_normal_dot, max_iter, min_relevant_area, min_quality_improvement)); 20 | return copy; 21 | } 22 | 23 | } 24 | 25 | #include 26 | 27 | using namespace geode; 28 | 29 | void wrap_improve_mesh() { 30 | GEODE_FUNCTION(improve_mesh); 31 | } 32 | -------------------------------------------------------------------------------- /geode/mesh/io.h: -------------------------------------------------------------------------------- 1 | // Mesh file I/O 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // Read a mesh format as triangle or polygon soup 9 | GEODE_EXPORT Tuple,Array>> read_soup(const string& filename); 10 | GEODE_EXPORT Tuple,Array>> read_polygon_soup(const string& filename); 11 | 12 | // Read a mesh format and convert to a manifold mesh. If the mesh is not manifold, an exception is thrown. 13 | GEODE_EXPORT Tuple,Array>> read_mesh(const string& filename); 14 | 15 | // Write a mesh to a file 16 | GEODE_EXPORT void write_mesh(const string& filename, const TriangleSoup& soup, RawArray> X); 17 | GEODE_EXPORT void write_mesh(const string& filename, const PolygonSoup& soup, RawArray> X); 18 | GEODE_EXPORT void write_mesh(const string& filename, const TriangleTopology& mesh, RawArray> X); 19 | 20 | // write a mesh to a file, assuming the mesh position are stored with the default 21 | // id and have type Vector. 22 | GEODE_EXPORT void write_mesh(const string &filename, const MutableTriangleTopology &mesh); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /geode/mesh/lower_hull.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace geode { 5 | 6 | Tuple, Array>> lower_hull(TriangleSoup const &imesh, Array> const &X, Vector up, const real ground_offset, const real draft_angle, const real division_angle); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /geode/mesh/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module mesh 3 | //##################################################################### 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_mesh() { 8 | GEODE_WRAP(ids) 9 | GEODE_WRAP(polygon_mesh) 10 | GEODE_WRAP(segment_soup) 11 | GEODE_WRAP(triangle_mesh) 12 | GEODE_WRAP(triangle_subdivision) 13 | GEODE_WRAP(halfedge_mesh) 14 | GEODE_WRAP(corner_mesh) 15 | GEODE_WRAP(mesh_io) 16 | GEODE_WRAP(lower_hull) 17 | GEODE_WRAP(decimate) 18 | GEODE_WRAP(improve_mesh) 19 | } 20 | -------------------------------------------------------------------------------- /geode/mesh/quadric.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace geode { 4 | 5 | Quadric compute_quadric(TriangleTopology const &mesh, const RawField, VertexId> X, VertexId v) { 6 | real total = 0; 7 | Quadric q; 8 | for (const auto e : mesh.outgoing(v)) { 9 | if (!mesh.is_boundary(e)) { 10 | total += q.add_face(mesh, X, mesh.face(e)); 11 | } 12 | } 13 | 14 | // Normalize 15 | if (total) { 16 | q *= 1/total; 17 | } 18 | 19 | return q; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/mesh/refine_mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace other { 5 | using namespace geode; 6 | 7 | // Insert new vertices and flip edges to improve quality of mesh 8 | // * Edges in resulting mesh should be close to target_edge_length +/- about 30% 9 | // * Average valence of vertices should be close to 6/4 for internal/boundary vertices 10 | void refine_mesh(MutableTriangleTopology& mesh, const FieldId x_id, 11 | const real target_edge_length, const int iterations=10); 12 | 13 | } -------------------------------------------------------------------------------- /geode/mesh/simplify.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | namespace geode { 4 | 5 | GEODE_CORE_EXPORT void 6 | simplify_inplace(MutableTriangleTopology& mesh, 7 | const FieldId,VertexId> X_id, // X must be a field managed by the mesh so that it will be properly updated if topological simplification creates new vertices 8 | const real distance, // (Very) approximate distance between original and simplified 9 | const real max_angle=pi/2, // Max normal angle change in radians for one simplification step 10 | const int min_vertices=-1, // Stop if we simplify down to this many vertices (-1 for no limit) 11 | const real boundary_distance=0); // How far we're allowed to move the boundary 12 | 13 | GEODE_CORE_EXPORT Tuple,Field,VertexId>> 14 | simplify(const TriangleTopology& mesh, 15 | RawField,VertexId> X, 16 | const real distance, // (Very) approximate distance between original and simplified 17 | const real max_angle=pi/2, // Max normal angle change in radians for one simplification step 18 | const int min_vertices=-1, // Stop if we simplify down to this many vertices (-1 for no limit) 19 | const real boundary_distance=0); // How far we're allowed to move the boundary 20 | 21 | 22 | } // geode namespace -------------------------------------------------------------------------------- /geode/mesh/test_lower_hull.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division 4 | 5 | from numpy import * 6 | from geode import TriangleSoup, lower_hull, write_mesh 7 | from geode.geometry.platonic import cube_mesh, icosahedron_mesh, sphere_mesh 8 | from geode.vector import relative_error 9 | 10 | def test_lower_hull(filename = None): 11 | mesh,X = icosahedron_mesh() 12 | mlh,Xlh = lower_hull(mesh, X, [0.3, 0.3, 1.0], -4., 5./180.*pi, 30./180.*pi) 13 | 14 | if filename is not None: 15 | write_mesh(filename+'-input.obj', mesh, X); 16 | write_mesh(filename+'-output.obj', mlh, Xlh); 17 | 18 | if __name__ == '__main__': 19 | test_lower_hull("lower_hull_test") 20 | -------------------------------------------------------------------------------- /geode/mesh/triangulate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace geode { 6 | 7 | // Generates a constrained Delaunay triangulation of the interior of a polygons (interior based on CCW winding) 8 | // Warning: This needs improvement. For now it may return junk in some cases 9 | // This occurs because constrained Delaunay triangulation requires intersection free edges but polygon csg constructs approximate intersection points that can introduce new self intersections 10 | // I suspect we will want either a version of polygon csg that resolves all self intersections and/or enabling insertion of new vertices during Delaunay triangulation 11 | Tuple,Field> triangulate_polygon(const Nested& raw_polygons); 12 | 13 | } // geode namespace -------------------------------------------------------------------------------- /geode/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module geode_wrap 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | using namespace geode; 8 | 9 | static bool has_exact() { 10 | #ifdef GEODE_GMP 11 | return true; 12 | #else 13 | return false; 14 | #endif 15 | } 16 | 17 | GEODE_PYTHON_MODULE(geode_wrap) { 18 | GEODE_WRAP(python) 19 | GEODE_WRAP(utility) 20 | 21 | #ifdef GEODE_PYTHON 22 | // Check for python exceptions in check_interrupts() 23 | add_interrupt_checker(check_python_interrupts); 24 | #endif 25 | 26 | GEODE_WRAP(math) 27 | GEODE_WRAP(array) 28 | GEODE_WRAP(vector) 29 | GEODE_WRAP(geometry) 30 | GEODE_WRAP(image) 31 | GEODE_WRAP(mesh) 32 | GEODE_WRAP(random) 33 | GEODE_WRAP(value) 34 | GEODE_WRAP(force) 35 | GEODE_WRAP(solver) 36 | GEODE_WRAP(structure) 37 | GEODE_WRAP(svg_to_bezier) 38 | #ifdef GEODE_GMP 39 | GEODE_WRAP(exact) 40 | #endif 41 | 42 | GEODE_FUNCTION(has_exact) 43 | } 44 | -------------------------------------------------------------------------------- /geode/openmesh/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | curvature.cpp 3 | decimate.cpp 4 | module.cpp 5 | triangulator.cpp 6 | TriMesh.cpp 7 | visualize.cpp 8 | ) 9 | 10 | set(module_HEADERS 11 | color_cast.h 12 | curvature.h 13 | decimate.h 14 | forward.h 15 | floodfill.h 16 | forward.h 17 | triangulator.h 18 | TriMesh.h 19 | visualize.h 20 | ) 21 | 22 | install_geode_headers(openmesh ${module_HEADERS}) 23 | 24 | add_geode_module(openmesh ${module_SRCS}) 25 | -------------------------------------------------------------------------------- /geode/openmesh/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2012, Otherlab. 2 | 3 | All rights reserved. 4 | -------------------------------------------------------------------------------- /geode/openmesh/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import platform 4 | if platform.system()=='Windows': 5 | from .. import geode_all as geode_wrap 6 | else: 7 | from .. import geode_wrap 8 | from numpy import inf 9 | 10 | def decimate_openmesh(mesh, max_collapses=(1<<31)-1, max_angle_error=90, max_quadric_error=inf, min_quality=1e-5): 11 | return geode_wrap.decimate_openmesh(mesh,max_collapses,max_angle_error,max_quadric_error,min_quality) 12 | -------------------------------------------------------------------------------- /geode/openmesh/color_cast.h: -------------------------------------------------------------------------------- 1 | // Work around a bug in OpenMesh color casting 2 | #pragma once 3 | 4 | #include 5 | 6 | #ifdef GEODE_OPENMESH 7 | namespace OpenMesh { 8 | 9 | template <> struct color_caster,Vec3f> { 10 | typedef geode::OVec return_type; 11 | static return_type cast(const Vec3f& src) { 12 | return return_type(uint8_t(255*src[0]),uint8_t(255*src[1]),uint8_t(255*src[2]),255); 13 | } 14 | }; 15 | template <> struct color_caster,Vec3uc> { 16 | typedef geode::OVec return_type; 17 | static return_type cast(const Vec3uc& src) { 18 | return return_type(src[0],src[1],src[2],255); 19 | } 20 | }; 21 | template <> struct color_caster,Vec4uc> { 22 | typedef geode::OVec return_type; 23 | static return_type cast(const Vec4uc& src) { 24 | return return_type(src[0],src[1],src[2],src[3]); 25 | } 26 | }; 27 | template <> struct color_caster> { 28 | typedef Vec3uc return_type; 29 | static return_type cast(const geode::OVec& src) { 30 | return return_type(src[0],src[1],src[2]); 31 | } 32 | }; 33 | template <> struct color_caster> { 34 | typedef Vec4uc return_type; 35 | static return_type cast(const geode::OVec& src) { 36 | return return_type(src[0],src[1],src[2],src[3]); 37 | } 38 | }; 39 | 40 | } 41 | 42 | #endif // GEODE_OPENMESH -------------------------------------------------------------------------------- /geode/openmesh/config.h: -------------------------------------------------------------------------------- 1 | // This file provides setup needed to include headers from OpenMesh 2 | #pragma once 3 | #include 4 | 5 | // Openmesh uses WIN32 instead of _WIN32 so we provide it 6 | #if defined(GEODE_OPENMESH) && defined(_WIN32) && !defined(WIN32) 7 | #define WIN32 _WIN32 8 | #endif 9 | 10 | #ifdef GEODE_OPENMESH 11 | #if defined(_WIN32) != defined(WIN32) 12 | #error OpenMesh uses 'WIN32' macro, which has not been configured to match _WIN32 13 | #endif 14 | 15 | // For MinGW we have to manually define OM_STATIC_BUILD since OpenMesh config doesn't expect gcc on windows 16 | #ifdef __MINGW32__ 17 | #define OM_STATIC_BUILD 1 18 | #endif 19 | 20 | // Since we're using hidden symbol visibility, dynamic_casts across shared library 21 | // boundaries are problematic. Therefore, don't use them even in debug mode. 22 | #define OM_FORCE_STATIC_CAST 23 | 24 | #endif // GEODE_OPENMESH -------------------------------------------------------------------------------- /geode/openmesh/curvature.h: -------------------------------------------------------------------------------- 1 | // Measure the mean and Gaussian curvatures of meshes 2 | #pragma once 3 | #ifdef GEODE_OPENMESH 4 | 5 | #include 6 | namespace geode { 7 | 8 | GEODE_CORE_EXPORT Field mean_curvatures(const TriMesh& mesh); 9 | GEODE_CORE_EXPORT Field gaussian_curvatures(const TriMesh& mesh); 10 | 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /geode/openmesh/forward.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #ifdef GEODE_OPENMESH 5 | namespace geode { 6 | 7 | class TriMesh; 8 | 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /geode/openmesh/visualize.cpp: -------------------------------------------------------------------------------- 1 | // Set colors on a TriMesh 2 | 3 | #include 4 | #ifdef GEODE_OPENMESH 5 | #include 6 | namespace geode { 7 | 8 | template<> GEODE_CORE_EXPORT void visualize(TriMesh& mesh, const function& color) { 9 | if (!mesh.has_vertex_colors()) 10 | mesh.request_vertex_colors(); 11 | for (auto vi = mesh.vertices_sbegin(); vi != mesh.vertices_end(); ++vi) 12 | mesh.set_color(vi,color(vi)); 13 | } 14 | 15 | template<> GEODE_CORE_EXPORT void visualize(TriMesh& mesh, const function& color) { 16 | if (!mesh.has_edge_colors()) 17 | mesh.request_edge_colors(); 18 | for (auto ei = mesh.edges_sbegin(); ei != mesh.edges_end(); ++ei) 19 | mesh.set_color(ei,color(ei)); 20 | } 21 | 22 | template<> GEODE_CORE_EXPORT void visualize(TriMesh& mesh, const function& color) { 23 | if (!mesh.has_face_colors()) 24 | mesh.request_face_colors(); 25 | for (auto fi = mesh.faces_sbegin(); fi != mesh.faces_end(); ++fi) 26 | mesh.set_color(fi,color(fi)); 27 | } 28 | 29 | } 30 | #endif // GEODE_OPENMESH 31 | -------------------------------------------------------------------------------- /geode/python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SOURCES 2 | Buffer.cpp 3 | Class.cpp 4 | ClassTest.cpp 5 | exceptions.cpp 6 | ExceptionValue.cpp 7 | from_python.cpp 8 | function.cpp 9 | numpy.cpp 10 | Object.cpp 11 | Ref.cpp 12 | repr.cpp 13 | try_convert.cpp 14 | wrap_constructor.cpp 15 | wrap_field.cpp 16 | wrap_function.cpp 17 | wrap_method.cpp 18 | wrap_property.cpp 19 | ) 20 | 21 | set(module_HEADERS 22 | Buffer.h 23 | cast.h 24 | Class.h 25 | config.h 26 | enum.h 27 | exceptions.h 28 | ExceptionValue.h 29 | forward.h 30 | from_python.h 31 | function.h 32 | module.h 33 | new.h 34 | numpy.h 35 | numpy-types.h 36 | Object.h 37 | outer_wrapper.h 38 | Ptr.h 39 | PyDictAdaptor.h 40 | pyrange.h 41 | Ref.h 42 | repr.h 43 | stl.h 44 | to_python.h 45 | try_convert.h 46 | utility.h 47 | wrap_call.h 48 | wrap_constructor.h 49 | wrap_field.h 50 | wrap_function.h 51 | wrap.h 52 | wrap_iter.h 53 | wrap_method.h 54 | wrap_property.h 55 | ) 56 | 57 | install_geode_headers(python ${module_HEADERS}) 58 | 59 | add_geode_module(python ${module_SOURCES}) 60 | -------------------------------------------------------------------------------- /geode/python/ExceptionValue.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ExceptionValue 3 | //##################################################################### 4 | // 5 | // A class for saving and rethrowing of exceptions. 6 | // 7 | // This is useful for implementing caching in situations where exceptions might be thrown. 8 | // ExceptionValues can be safely copied around. 9 | // 10 | //##################################################################### 11 | #pragma once 12 | 13 | #include 14 | namespace geode { 15 | 16 | class SavedExceptionBase; 17 | 18 | class ExceptionValue { 19 | public: 20 | typedef ExceptionValue Self; 21 | shared_ptr error; 22 | 23 | ExceptionValue() {} 24 | GEODE_CORE_EXPORT ExceptionValue(const std::exception& e); 25 | 26 | GEODE_CORE_EXPORT void throw_() const; 27 | 28 | explicit operator bool() const { 29 | return bool(error); 30 | } 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /geode/python/Frozen.py: -------------------------------------------------------------------------------- 1 | '''Base class to freeze the fields of Python objects''' 2 | 3 | import contextlib 4 | 5 | class Frozen(object): 6 | '''Inheriting from Frozen disallows new field creation except inside a thaw block''' 7 | 8 | def __setattr__(self,key,value): 9 | if hasattr(self,key) or hasattr(self,'_thawed'): 10 | object.__setattr__(self,key,value) 11 | else: 12 | raise TypeError("%s is a frozen class; can't create field '%s' outside a thaw block"%(type(self).__name__,key)) 13 | 14 | @contextlib.contextmanager 15 | def thaw(self): 16 | '''Temporarily allow creation of new fields''' 17 | object.__setattr__(self,'_thawed',True) 18 | try: 19 | yield 20 | finally: 21 | object.__delattr__(self,'_thawed') 22 | 23 | class Immutable(Frozen): 24 | '''Inheriting from Immutable disallows setting fields except inside a thaw block''' 25 | def __setattr__(self,key,value): 26 | if hasattr(self,'_thawed'): 27 | object.__setattr__(self,key,value) 28 | else: 29 | raise TypeError("%s is an immutable class; can't set field '%s' outside a thaw block"%(type(self).__name__,key)) 30 | -------------------------------------------------------------------------------- /geode/python/Object.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Object 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | GEODE_DEFINE_TYPE(Object) 10 | 11 | Object::Object() { 12 | #ifndef NDEBUG 13 | const auto self = (PyObject*)this-1; 14 | // Partially check that object was constructed inside new_ or a wrapped constructor 15 | assert(self->ob_refcnt==1 && "Maybe object built outside new_, or compile mixes GEODE_PYTHON and !GEODE_PYTHON"); 16 | #endif 17 | } 18 | 19 | Object::~Object() {} 20 | 21 | } 22 | using namespace geode; 23 | 24 | void wrap_object() { 25 | Class("Object") 26 | .GEODE_INIT(); 27 | } 28 | -------------------------------------------------------------------------------- /geode/python/PyDictAdaptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace geode { 5 | 6 | #ifdef GEODE_PYTHON 7 | 8 | class PyDictAdaptor { 9 | const Ref<> dict; 10 | public: 11 | 12 | PyDictAdaptor() 13 | : dict(steal_ref_check(PyDict_New())) {} 14 | 15 | template void set(const K& k, const V& v) { 16 | Ref<> py_k = to_python_ref(k); 17 | Ref<> py_v = to_python_ref(v); 18 | PyDict_SetItem(&*dict, &*py_k, &*py_v); 19 | } 20 | 21 | template Ptr<> get(const K& k) { 22 | return ptr(PyDict_GetItem(&*dict, k)); 23 | } 24 | 25 | const Ref<>& operator*() { 26 | return dict; 27 | } 28 | }; 29 | 30 | #else // non-python stub 31 | 32 | class PyDictAdaptor { 33 | public: 34 | PyDictAdaptor() {} 35 | template void set(const K& k, const V& v) { throw_no_python(); } 36 | template Ptr<> get(const K& k) { throw_no_python(); } 37 | const Ref<>& operator*() { throw_no_python(); } 38 | }; 39 | 40 | #endif 41 | } 42 | -------------------------------------------------------------------------------- /geode/python/Ref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace geode { 3 | 4 | void throw_self_owner_mismatch() { 5 | throw AssertionError("can't convert Ref/Ptr Ref/Ptr; self is different from owner"); 6 | } 7 | 8 | #ifdef GEODE_PYTHON 9 | void set_self_owner_mismatch() { 10 | PyErr_Format(PyExc_AssertionError, "can't convert Ref or Ptr to python; self is different from owner"); 11 | } 12 | #endif 13 | 14 | } 15 | -------------------------------------------------------------------------------- /geode/python/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | -------------------------------------------------------------------------------- /geode/python/function.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Conversion for functions 3 | //##################################################################### 4 | #include 5 | namespace geode { 6 | 7 | #ifdef GEODE_PYTHON 8 | 9 | void throw_callable_error(PyObject* object) { 10 | PyErr_Format(PyExc_TypeError,"expected callable object, got %s",object->ob_type->tp_name); 11 | throw PythonError(); 12 | } 13 | 14 | #endif 15 | } 16 | -------------------------------------------------------------------------------- /geode/python/repr.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function repr 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | using std::string; 11 | 12 | template inline string repr(const T& x) { 13 | return x.repr(); 14 | } 15 | 16 | GEODE_CORE_EXPORT string repr(PyObject& x); 17 | GEODE_CORE_EXPORT string repr(PyObject* x); 18 | GEODE_CORE_EXPORT string repr(const float x); 19 | GEODE_CORE_EXPORT string repr(const double x); 20 | GEODE_CORE_EXPORT string repr(const long double x); 21 | GEODE_CORE_EXPORT string repr(const string& s); 22 | GEODE_CORE_EXPORT string repr(const char* s); 23 | 24 | // Make repr work on nonconst char arrays 25 | static inline string repr(char s[]) { 26 | const char* p = s; 27 | return repr(p); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /geode/python/test_convert.py: -------------------------------------------------------------------------------- 1 | from geode import * 2 | import ast 3 | 4 | def test_list(): 5 | x = [1,2,3] 6 | y = list_convert_test(x) 7 | assert type(x)==type(y) 8 | assert x==y 9 | 10 | def test_set(): 11 | x = set([1,2,3]) 12 | y = set_convert_test(x) 13 | assert type(x)==type(y) 14 | 15 | def test_dict(): 16 | x = {1:'a',2:'b',3:'c'} 17 | y = dict_convert_test(x) 18 | assert type(x)==type(y) 19 | assert x==y 20 | 21 | def test_enum(): 22 | a = EnumTestA 23 | aa = enum_convert_test(a) 24 | assert a==aa 25 | assert a is aa 26 | assert str(a)=='EnumTestA' 27 | 28 | def test_str_repr(): 29 | for i in xrange(256): 30 | c = chr(i) 31 | r = str_repr_test(c) 32 | assert ast.literal_eval(r)==c 33 | if c != "'": 34 | assert repr(c)==r 35 | -------------------------------------------------------------------------------- /geode/python/test_frozen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import with_statement 4 | from geode.python.Frozen import Frozen,Immutable 5 | 6 | def test_frozen(): 7 | a = Frozen() 8 | try: 9 | a.x = 0 10 | assert False 11 | except TypeError: 12 | pass 13 | with a.thaw(): 14 | a.x = 0 15 | a.x = 1 16 | try: 17 | a.y = 0 18 | assert False 19 | except TypeError: 20 | pass 21 | 22 | def test_immutable(): 23 | a = Immutable() 24 | try: 25 | a.x = 0 26 | assert False 27 | except TypeError: 28 | pass 29 | with a.thaw(): 30 | a.x = 0 31 | try: 32 | a.x = 0 33 | assert False 34 | except TypeError: 35 | pass 36 | try: 37 | a.y = 0 38 | assert False 39 | except TypeError: 40 | pass 41 | -------------------------------------------------------------------------------- /geode/python/try_convert.cpp: -------------------------------------------------------------------------------- 1 | // Convert to and from python if possible, otherwise throw an exception 2 | 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | #ifdef GEODE_PYTHON 8 | 9 | void set_to_python_failed(const type_info& type) { 10 | PyErr_Format(PyExc_TypeError,"C++ type %s can't be converted to Python: no to_python overload exists",type.name()); 11 | } 12 | 13 | void from_python_failed(PyObject* object, const type_info& type) { 14 | throw TypeError(format("Python type %s can't be converted to C++ type %s: no from_python overload exists",object->ob_type->tp_name,type.name())); 15 | } 16 | 17 | #endif 18 | 19 | } 20 | -------------------------------------------------------------------------------- /geode/python/wrap_constructor.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function Wrap_Constructor 3 | //##################################################################### 4 | #include 5 | #ifdef GEODE_PYTHON 6 | #include 7 | namespace geode { 8 | 9 | void set_argument_count_error(int desired,PyObject* args,PyObject* kwds) { 10 | Py_ssize_t size = PyTuple_GET_SIZE(args); 11 | if (size!=desired) { 12 | if (!desired) 13 | GEODE_CALL_PyErr_Format(PyExc_TypeError,"constructor takes no arguments (%zd given)",size); 14 | else 15 | GEODE_CALL_PyErr_Format(PyExc_TypeError,"constructor takes %d argument%s (%zd given)",desired,(desired>1?"s":""),size); 16 | } else 17 | PyErr_SetString(PyExc_TypeError,"constructor takes no keyword arguments"); 18 | } 19 | 20 | void handle_constructor_error(PyObject* self,const std::exception& error) { 21 | // Deallocate self without calling the destructor, since the constructor didn't finish. 22 | // We don't need to call Py_DECREF since we know that no one else owns self yet. 23 | free(self); 24 | 25 | // report the error 26 | set_python_exception(error); 27 | } 28 | 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /geode/python/wrap_field.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function wrap_field 3 | //##################################################################### 4 | #include 5 | #ifdef GEODE_PYTHON 6 | #include 7 | namespace geode { 8 | 9 | PyObject* wrap_field_helper(PyTypeObject* type,const char* name,size_t offset,getter get,setter set) { 10 | // Allocate PyGetSetDef 11 | PyGetSetDef* def = (PyGetSetDef*)malloc(sizeof(PyGetSetDef)); 12 | if (!def) throw std::bad_alloc(); 13 | memset(def,0,sizeof(PyGetSetDef)); 14 | 15 | // Fill in fields 16 | def->name = (char*)name; 17 | def->get = get; 18 | def->set = set; 19 | def->closure = (void*)offset; 20 | 21 | // allocate property 22 | PyObject* descr = PyDescr_NewGetSet(type,def); 23 | if (!descr) throw PythonError(); 24 | return descr; 25 | } 26 | 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /geode/python/wrap_method.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function wrap_method 3 | //##################################################################### 4 | #include 5 | #ifdef GEODE_PYTHON 6 | #include 7 | namespace geode { 8 | 9 | PyObject* wrap_method_helper(PyTypeObject* type,const char* name,wrapperfunc wrapper,void* method) { 10 | // Allocate wrapperbase 11 | wrapperbase* base = (wrapperbase*)malloc(sizeof(wrapperbase)); 12 | if (!base) throw std::bad_alloc(); 13 | memset(base,0,sizeof(wrapperbase)); 14 | 15 | // Fill in fields 16 | base->name = (char*)name; 17 | base->wrapper = wrapper; 18 | base->flags = 0; // no keyword args 19 | 20 | // Allocate wrapper 21 | PyObject* descr = PyDescr_NewWrapper(type,base,method); 22 | if (!descr) throw PythonError(); 23 | return descr; 24 | } 25 | 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /geode/python/wrap_property.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef GEODE_PYTHON 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | PyObject* wrap_property_helper(PyTypeObject* type,const char* name,getter get_wrapper,setter set_wrapper,void* getset) { 8 | // Make a PyGetSetDef 9 | PyGetSetDef* def = (PyGetSetDef*)malloc(sizeof(PyGetSetDef)); 10 | memset(def,0,sizeof(PyGetSetDef)); 11 | def->name = const_cast_(name); 12 | def->get = get_wrapper; 13 | def->set = set_wrapper; 14 | def->closure = getset; 15 | 16 | // Allocate descriptor 17 | PyObject* descr = PyDescr_NewGetSet(type,def); 18 | if (!descr) throw_python_error(); 19 | return descr; 20 | } 21 | 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /geode/random/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | counter.cpp 3 | permute.cpp 4 | Random.cpp 5 | Sobol.cpp 6 | ) 7 | 8 | set(module_HEADERS 9 | counter.h 10 | forward.h 11 | permute.h 12 | Random.h 13 | Sobol.h 14 | ) 15 | 16 | install_geode_headers(random ${module_HEADERS}) 17 | 18 | add_geode_module(random ${module_SRCS}) 19 | -------------------------------------------------------------------------------- /geode/random/Sobol.h: -------------------------------------------------------------------------------- 1 | // Class Sobol: Low discrepancy quasirandom numbers 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template class Box; 12 | using std::numeric_limits; 13 | 14 | template 15 | class Sobol : public Object { 16 | public: 17 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 18 | 19 | typedef typename TV::Scalar T; 20 | static_assert(numeric_limits::radix==2,""); 21 | static const int max_bits = numeric_limits::digits; 22 | typedef typename mpl::if_c<(max_bits<=30),uint32_t,uint64_t>::type TI; // pick an integer large enough to hold T's mantissa 23 | static_assert(numeric_limits::digits>max_bits,""); 24 | enum Workaround {d=TV::m}; 25 | 26 | private: 27 | const TV offset, scales; 28 | Vector x; // Last result 29 | TI n; 30 | private: 31 | GEODE_CORE_EXPORT Sobol(const Box& box); 32 | public: 33 | ~Sobol(); 34 | 35 | GEODE_CORE_EXPORT TV vector(); 36 | }; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /geode/random/__init__.py: -------------------------------------------------------------------------------- 1 | """random module""" 2 | 3 | from __future__ import (division,absolute_import) 4 | 5 | from geode import * 6 | 7 | Sobols = {1:Sobol1d,2:Sobol2d,3:Sobol3d} 8 | def Sobol(box): 9 | return Sobols[len(box.min)](box) 10 | -------------------------------------------------------------------------------- /geode/random/counter.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Counter-based random numbers 3 | //##################################################################### 4 | #define __STDC_CONSTANT_MACROS 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | uint128_t threefry(uint128_t key, uint128_t ctr) { 11 | threefry2x64_ctr_t c,k; 12 | uint64_t mask = -1; 13 | c.v[0] = ctr&mask; 14 | c.v[1] = (ctr>>64)&mask; 15 | k.v[0] = key&mask; 16 | k.v[1] = (key>>64)&mask; 17 | threefry2x64_ctr_t r = threefry2x64(c,k); 18 | return (uint128_t(r.v[1])<<64)|r.v[0]; 19 | } 20 | 21 | } 22 | using namespace geode; 23 | 24 | void wrap_counter() { 25 | GEODE_FUNCTION(threefry) 26 | } 27 | -------------------------------------------------------------------------------- /geode/random/counter.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Counter-based random numbers 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | // Note that we put key first to match currying, unlike Salmon et al. 11 | GEODE_CORE_EXPORT uint128_t threefry(uint128_t key, uint128_t ctr) GEODE_CONST; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /geode/random/forward.h: -------------------------------------------------------------------------------- 1 | // Random forward declarations 2 | 3 | #pragma once 4 | 5 | namespace geode { 6 | 7 | class Random; 8 | template class Sobol; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /geode/random/module.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Module Random 3 | //##################################################################### 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_random() { 8 | GEODE_WRAP(Random) 9 | GEODE_WRAP(sobol) 10 | GEODE_WRAP(counter) 11 | GEODE_WRAP(permute) 12 | } 13 | -------------------------------------------------------------------------------- /geode/random/permute.h: -------------------------------------------------------------------------------- 1 | // Random access pseudorandom permutations 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // Apply a pseudorandom permutation to the range [0,n-1] 9 | GEODE_CORE_EXPORT uint64_t random_permute(uint64_t n, uint128_t key, uint64_t x) GEODE_CONST; 10 | GEODE_CORE_EXPORT uint64_t random_unpermute(uint64_t n, uint128_t key, uint64_t x) GEODE_CONST; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /geode/random/random123/README: -------------------------------------------------------------------------------- 1 | This directory contains a subset of files from Random123 by Salmon et al. at D. E. Shaw Research. 2 | See http://deshawresearch.com/resources_random123.html for the paper and full source code. 3 | -------------------------------------------------------------------------------- /geode/solver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | brent.cpp 3 | pattern_max.cpp 4 | powell.cpp 5 | ) 6 | 7 | set(module_HEADERS 8 | brent.h 9 | pattern_max.h 10 | powell.h 11 | quadratic.h 12 | ) 13 | 14 | install_geode_headers(solver ${module_HEADERS}) 15 | 16 | add_geode_module(solver ${module_SRCS}) 17 | -------------------------------------------------------------------------------- /geode/solver/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otherlab/geode/18ccf114f02ca733a92b223541161f0405f12535/geode/solver/__init__.py -------------------------------------------------------------------------------- /geode/solver/brent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Brent's method for one-dimensional optimization. The implementation 4 | // is taken from scipy, which requires the following notice: 5 | // ******NOTICE*************** 6 | // optimize.py module by Travis E. Oliphant 7 | // 8 | // You may copy and use this module as you see fit with no 9 | // guarantee implied provided you keep this notice in all copies. 10 | // *****END NOTICE************ 11 | 12 | #include 13 | #include 14 | #include 15 | namespace geode { 16 | 17 | // Minimize a one-dimensional function using Brent's method. Unlike scipy, all tolerances are absolute. 18 | // Arguments: 19 | // bracket: a starting interval (a,b) for bracketing (the solution is not necessarily inside this range) 20 | // x: starting point 21 | // xtol: absolute point tolerance 22 | // ftol: absolute function value tolerance 23 | // x is updated to minimize f(x), and x,f(x),iters is returned. 24 | GEODE_CORE_EXPORT Tuple brent(const function& f, Vector bracket, real xtol, int maxiter); 25 | 26 | // Same as above, but specify the full bracketing interval explicitly. bracket = (a,b,c) must satisfy b in [a,c], f(b) < f(a),f(c). 27 | GEODE_CORE_EXPORT Tuple brent(const function& f, Vector bracket, real xtol, int maxiter); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /geode/solver/module.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void wrap_solver() { 4 | GEODE_WRAP(brent) 5 | GEODE_WRAP(powell) 6 | } 7 | -------------------------------------------------------------------------------- /geode/solver/pattern_max.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace geode { 4 | 5 | real spherical_pattern_maximize(const function)>& score, Vector& n, real tol) { 6 | static const real da = 2*pi/5; 7 | static const Vector dirs[5] = {polar(0.), polar(da), polar(2*da), polar(3*da), polar(4*da)}; 8 | const real alpha = .5; 9 | real step = .2; 10 | real dot = score(n); 11 | while (step > tol) { 12 | real best_dot = dot; 13 | Vector best_n = n; 14 | Vector orth; 15 | orth[n.argmin()] = 1; 16 | Vector a = cross(n,orth).normalized(), b = cross(n,a); 17 | for (int i = 0; i < 5; i++) { 18 | Vector candidate = (n + step*dirs[i].x*a + step*dirs[i].y*b).normalized(); 19 | real d = score(candidate); 20 | if (best_dot < d) { 21 | best_dot = d; 22 | best_n = candidate; 23 | } 24 | } 25 | if (dot < best_dot) { 26 | dot = best_dot; 27 | n = best_n; 28 | } else 29 | step *= alpha; 30 | } 31 | return dot; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /geode/solver/pattern_max.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | // Maximize a functional over a sphere using pattern search 8 | GEODE_CORE_EXPORT real spherical_pattern_maximize(const function)>& score, Vector& n, real tol); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /geode/solver/powell.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Powell's method for multidimensional optimization. The implementation 4 | // is taken from scipy, which requires the following notice: 5 | // ******NOTICE*************** 6 | // optimize.py module by Travis E. Oliphant 7 | // 8 | // You may copy and use this module as you see fit with no 9 | // guarantee implied provided you keep this notice in all copies. 10 | // *****END NOTICE************ 11 | 12 | #include 13 | #include 14 | #include 15 | namespace geode { 16 | 17 | // Minimize a multidimensional function using Powell's method. Unlike scipy, all tolerances are absolute. 18 | // Arguments: 19 | // x: starting point 20 | // scale: initial step size 21 | // xtol: absolute point tolerance 22 | // ftol: absolute function value tolerance 23 | GEODE_CORE_EXPORT Tuple powell(const function)>& f, RawArray x, real scale, real xtol, real ftol, int maxiter); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /geode/solver/quadratic.h: -------------------------------------------------------------------------------- 1 | // Quadratic formula 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | template static inline Vector solve_quadratic(const T a, const T b, const T c) { 9 | const T disc = sqr(b)-4*a*c; 10 | if (disc < 0) { 11 | const T nan = numeric_limits::quiet_NaN(); 12 | return vec(nan,nan); 13 | } 14 | const T num = -.5*(b+copysign(sqrt(disc),b)); 15 | return vec(num/a,c/num); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /geode/structure/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | Heap.cpp 3 | Tuple.cpp 4 | ) 5 | 6 | set(module_HEADERS 7 | Empty.h 8 | forward.h 9 | Hashtable.h 10 | Heap.h 11 | OperationHash.h 12 | Pair.h 13 | Quad.h 14 | Queue.h 15 | Quintuple.h 16 | Singleton.h 17 | Stack.h 18 | Triple.h 19 | Tuple.h 20 | UnionFind.h 21 | ) 22 | 23 | install_geode_headers(structure ${module_HEADERS}) 24 | 25 | add_geode_module(structure ${module_SRCS}) 26 | -------------------------------------------------------------------------------- /geode/structure/Empty.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Tuple<> 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include // needed to avoid header bug on Mac OS X 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | namespace geode { 15 | 16 | template<> 17 | class Tuple<> { 18 | public: 19 | bool operator==(const Tuple p) const { 20 | return true; 21 | } 22 | 23 | bool operator!=(const Tuple p) const { 24 | return false; 25 | } 26 | 27 | bool operator<(const Tuple p) const { 28 | return false; 29 | } 30 | 31 | bool operator>(const Tuple p) const { 32 | return false; 33 | } 34 | 35 | void get() const {} 36 | }; 37 | 38 | static inline std::istream& operator>>(std::istream& input,Tuple<> p) { 39 | return input>>expect('(')>>expect(')'); 40 | } 41 | 42 | static inline std::ostream& operator<<(std::ostream& output,Tuple<> p) { 43 | return output<<"()"; 44 | } 45 | 46 | static inline int hash_reduce(Tuple<> key) { 47 | return 0; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /geode/structure/Heap.cpp: -------------------------------------------------------------------------------- 1 | // A flexible binary heap template 2 | 3 | #include 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | namespace { 9 | struct HeapTest : public HeapBase { 10 | typedef HeapBase Base; 11 | Array heap; 12 | 13 | HeapTest(Array heap) 14 | : heap(heap) {} 15 | 16 | int size() const { return heap.size(); } 17 | bool first(const int i, const int j) const { return heap[i] <= heap[j]; } 18 | void swap(const int i, const int j) { std::swap(heap[i],heap[j]); } 19 | 20 | int pop() { 21 | GEODE_ASSERT(size()); 22 | const auto x = heap[0]; 23 | swap(0,size()-1); 24 | heap.pop(); 25 | if (size()) 26 | Base::move_downward(0); 27 | return x; 28 | } 29 | }; 30 | } 31 | 32 | static Array heapsort_test(RawArray input) { 33 | HeapTest H(input.copy()); 34 | H.make(); 35 | GEODE_ASSERT(H.is_heap()); 36 | Array order; 37 | while (H.size()) { 38 | order.append(H.pop()); 39 | GEODE_ASSERT(H.is_heap()); 40 | } 41 | return order; 42 | } 43 | 44 | } 45 | using namespace geode; 46 | 47 | void wrap_heap() { 48 | GEODE_FUNCTION(heapsort_test) 49 | } 50 | -------------------------------------------------------------------------------- /geode/structure/OperationHash.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class OperationHash 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | class OperationHash { 11 | public: 12 | Array operations; 13 | unsigned int current_operation; 14 | 15 | OperationHash(const int m=0) 16 | : operations(m), current_operation(1) {} 17 | 18 | void initialize(const int m) { 19 | if (m==operations.size()) 20 | return next_operation(); 21 | operations.copy(constant_map(m,0u)); 22 | current_operation = 1; 23 | } 24 | 25 | void mark(const int i) { 26 | operations[i] = current_operation; 27 | } 28 | 29 | void unmark(const int i) { 30 | operations[i] = 0; 31 | } 32 | 33 | bool is_marked_current(const int i) const { 34 | return operations[i]==current_operation; 35 | } 36 | 37 | void next_operation() { 38 | current_operation++; 39 | if (!current_operation) { 40 | current_operation = 1; 41 | operations.fill(0); // reset everything if overflow 42 | } 43 | } 44 | 45 | void remove_duplicates(Array& list) { 46 | next_operation(); 47 | for (int i=list.size()-1;i>1;i--) { 48 | if (is_marked_current(list[i])) 49 | list.remove_index_lazy(i); 50 | else 51 | mark(list[i]); 52 | } 53 | next_operation(); 54 | } 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /geode/structure/Stack.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Stack 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | template 10 | class Stack { 11 | public: 12 | Array array; 13 | 14 | Stack() {} 15 | 16 | void clean_memory() { 17 | array.clean_memory(); 18 | } 19 | 20 | void preallocate(const int max_size) { 21 | array.preallocate(max_size); 22 | } 23 | 24 | void increase_size(const int size) { 25 | array.preallocate(size+array.m); 26 | } 27 | 28 | void compact() { 29 | array.compact(); 30 | } 31 | 32 | void push(const T& element) GEODE_ALWAYS_INLINE { 33 | array.append(element); 34 | } 35 | 36 | T pop() { 37 | return array.pop(); 38 | } 39 | 40 | const T& peek() const { 41 | return array.back(); 42 | } 43 | 44 | bool empty() const { 45 | return array.m==0; 46 | } 47 | 48 | void clear() { 49 | array.clear(); 50 | } 51 | 52 | void swap(Stack& stack) { 53 | array.swap(stack.array); 54 | } 55 | }; 56 | 57 | } 58 | namespace std { 59 | template void swap(geode::Stack& stack1,geode::Stack& stack2) { 60 | stack1.swap(stack2); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /geode/structure/Tuple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace geode { 3 | 4 | #ifdef GEODE_PYTHON 5 | void throw_tuple_mismatch_error(int expected, int got) { 6 | PyErr_Format(PyExc_TypeError,"expected tuple of length %d, got %d",expected,got); 7 | throw_python_error(); 8 | } 9 | #endif 10 | 11 | } 12 | -------------------------------------------------------------------------------- /geode/structure/forward.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header DataStructuresForward 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include // Must be included first 7 | namespace geode { 8 | 9 | // Convenience empty class 10 | struct Unit {}; 11 | static const Unit unit = Unit(); 12 | 13 | #ifdef GEODE_VARIADIC 14 | template class Tuple; 15 | #else 16 | template class Tuple; 17 | #endif 18 | 19 | class UnionFind; 20 | 21 | class OperationHash; 22 | template class Queue; 23 | template class Stack; 24 | 25 | template struct HashtableEntry; 26 | template class Hashtable; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /geode/structure/module.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace geode; 3 | 4 | void wrap_structure() { 5 | GEODE_WRAP(heap) 6 | } 7 | -------------------------------------------------------------------------------- /geode/structure/test_heap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import division,print_function 4 | from geode import * 5 | from numpy import random 6 | 7 | def test_heap(): 8 | random.seed(83131) 9 | for n in xrange(30): 10 | for m in 2,max(n//3,1),1000: 11 | x = random.randint(m,size=n).astype(int32) 12 | y = heapsort_test(x) 13 | assert all(sort(x)==y) 14 | 15 | if __name__=='__main__': 16 | test_heap() 17 | -------------------------------------------------------------------------------- /geode/svg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_geode_module(svg_to_bezier svg_to_bezier.cpp nanosvg/nanosvg.cpp NO_MODULE) 2 | -------------------------------------------------------------------------------- /geode/svg/svg_to_bezier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | using std::vector; 11 | using std::string; 12 | 13 | // a path (all subpaths) and its style 14 | class SVGStyledPath: public Object { 15 | public: 16 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 17 | 18 | unsigned int fillColor; 19 | unsigned int strokeColor; 20 | float strokeWidth; 21 | int hasFill; 22 | int fillRule; // 1 for nonzero (default), 2 for evenodd 23 | bool hasStroke; 24 | string CSSclass; 25 | 26 | unsigned int elementIndex; 27 | vector>> shapes; 28 | 29 | protected: 30 | SVGStyledPath(unsigned int _elementIndex) 31 | : elementIndex(_elementIndex) 32 | {} 33 | }; 34 | 35 | GEODE_CORE_EXPORT vector> svgfile_to_styled_beziers(const string& filename); 36 | GEODE_CORE_EXPORT vector> svgstring_to_styled_beziers(const string& svgstring); 37 | 38 | GEODE_CORE_EXPORT vector>> svgfile_to_beziers(const string& filename); 39 | GEODE_CORE_EXPORT vector>> svgstring_to_beziers(const string& svgstring); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /geode/utility/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | base64.cpp 3 | CloneArray.cpp 4 | curry.cpp 5 | debug.cpp 6 | DebugPrint.cpp 7 | format.cpp 8 | interrupts.cpp 9 | Log.cpp 10 | LogEntry.cpp 11 | LogScope.cpp 12 | module.cpp 13 | path.cpp 14 | process.cpp 15 | ProgressIndicator.cpp 16 | resource.cpp 17 | stream.cpp 18 | time.cpp 19 | ) 20 | 21 | set(module_HEADERS 22 | base64.h 23 | Cloneable.h 24 | CloneArray.h 25 | compose.h 26 | config.h 27 | const_cast.h 28 | convert_case.h 29 | CopyConst.h 30 | c_str.h 31 | curry.h 32 | debug.h 33 | DebugPrint.h 34 | endian.h 35 | enumerate.h 36 | equals.h 37 | format.h 38 | forward.h 39 | from_string.h 40 | function.h 41 | HasCheapCopy.h 42 | Hasher.h 43 | IdSet.h 44 | interrupts.h 45 | IRange.h 46 | LogEntry.h 47 | Log.h 48 | LogScope.h 49 | macro_map.h 50 | move.h 51 | mpl.h 52 | openmp.h 53 | overload.h 54 | pass.h 55 | path.h 56 | prioritize.h 57 | process.h 58 | ProgressIndicator.h 59 | Protect.h 60 | range.h 61 | remove_commas.h 62 | resource.h 63 | rounding.h 64 | SanitizeFunction.h 65 | smart_ptr.h 66 | STATIC_ASSERT_SAME.h 67 | stl.h 68 | stream.h 69 | str.h 70 | time.h 71 | tr1.h 72 | type_traits.h 73 | Unique.h 74 | using.h 75 | validity.h 76 | ) 77 | 78 | install_geode_headers(utility ${module_HEADERS}) 79 | 80 | add_geode_module(utility ${module_SRCS}) 81 | -------------------------------------------------------------------------------- /geode/utility/CloneArray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | namespace geode { 3 | 4 | CloneArray:: 5 | CloneArray(const CloneableBase& template_object, const int count) 6 | : sizeof_clone(template_object.sizeof_clone()), count(count) { 7 | assert(count>=0); 8 | data = (char*)malloc(sizeof_clone*count); 9 | int i = 0; 10 | try { 11 | for(;i:: 22 | ~CloneArray() { 23 | for(int i=0;i 7 | namespace geode { 8 | 9 | template struct CopyConst{typedef T type;}; 10 | template struct CopyConst:public add_const{}; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /geode/utility/DebugPrint.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Macro GEODE_DEBUG_PRINT 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | void debug_print_helper(const char* prefix,...) { 10 | Log::cerr< 7 | #include 8 | #include 9 | #include 10 | #include 11 | namespace geode { 12 | 13 | using std::string; 14 | 15 | class LogEntry : public Noncopyable { 16 | public: 17 | LogEntry* parent; 18 | int depth; 19 | double time; 20 | double timer_start_time; 21 | string name; 22 | bool end_on_separate_line,log_file_end_on_separate_line; 23 | static bool start_on_separate_line,log_file_start_on_separate_line; 24 | static bool needs_indent,log_file_needs_indent; 25 | int& verbosity_level; 26 | 27 | LogEntry(LogEntry* parent, const int depth, const string& name, int& verbosity_level); 28 | virtual ~LogEntry(); 29 | 30 | void start(FILE* log_file); 31 | void stop(FILE* log_file); 32 | virtual LogEntry* get_stop_time(FILE* log_file); 33 | virtual LogEntry* get_new_scope(FILE* log_file,const string& new_name); 34 | virtual LogEntry* get_new_item(FILE* log_file,const string& new_name); 35 | virtual LogEntry* get_pop_scope(FILE* log_file); 36 | virtual void dump_log(FILE* output); 37 | virtual void dump_names(FILE* output); 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /geode/utility/LogScope.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class LogScope 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace geode { 11 | 12 | using std::string; 13 | using std::vector; 14 | 15 | class LogScope : public LogEntry { 16 | public: 17 | unordered_map entries; 18 | vector children; 19 | string scope_identifier; 20 | 21 | LogScope(LogEntry* parent, int depth, const string& scope_identifier, const string& name, int& verbosity_level); 22 | virtual ~LogScope(); 23 | 24 | LogEntry* get_stop_time(FILE* log_file); 25 | string name_to_identifier(const string& name); 26 | LogEntry* get_new_scope(FILE* log_file,const string& new_name); 27 | LogEntry* get_new_item(FILE* log_file,const string& new_name); 28 | LogEntry* get_pop_scope(FILE* log_file); 29 | void dump_log(FILE* output); 30 | void dump_names(FILE* output); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /geode/utility/ProgressIndicator.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ProgressIndicator 3 | //##################################################################### 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | ProgressIndicator::ProgressIndicator(const int total, const bool brief) 9 | : total(total), brief(brief), done(0), percent_done(0), print(true) {} 10 | 11 | void ProgressIndicator::initialize(const int total_input) { 12 | total = total_input; 13 | done = percent_done = 0; 14 | } 15 | 16 | bool ProgressIndicator::progress(const int by) { 17 | done += by; 18 | int new_percent_done = 100*done/total; 19 | if (new_percent_done>percent_done){ 20 | percent_done = new_percent_done; 21 | if (print) { 22 | if (brief) 23 | Log::cout<<'.'< 7 | namespace geode { 8 | 9 | class ProgressIndicator { 10 | public: 11 | int total; 12 | bool brief; 13 | int done; 14 | int percent_done; 15 | bool print; 16 | 17 | GEODE_CORE_EXPORT ProgressIndicator(const int total=1, const bool brief=false); 18 | GEODE_CORE_EXPORT void initialize(const int total_input); 19 | GEODE_CORE_EXPORT bool progress(const int by=1); 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/utility/Protect.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Macro GEODE_PROTECT 3 | //##################################################################### 4 | #pragma once 5 | 6 | #define GEODE_PROTECT(...) __VA_ARGS__ 7 | -------------------------------------------------------------------------------- /geode/utility/STATIC_ASSERT_SAME.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Macro STATIC_ASSERT_SAME 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template struct AssertSame { static const bool value = false; }; 9 | template struct AssertSame { static const bool value = true; }; 10 | 11 | #define STATIC_ASSERT_SAME(T0,T1) \ 12 | static_assert(geode::AssertSame::value,"Given types do not match") 13 | 14 | } 15 | -------------------------------------------------------------------------------- /geode/utility/__init__.py: -------------------------------------------------------------------------------- 1 | """utility module""" 2 | 3 | from __future__ import absolute_import 4 | from . import Log 5 | import platform 6 | import tempfile 7 | import types 8 | import os 9 | 10 | if platform.system()=='Windows': 11 | from ..geode_all import resource_py,cache 12 | else: 13 | from ..geode_wrap import resource_py,cache 14 | 15 | def curry(f,*a,**k): 16 | def g(*a2,**k2): 17 | k3 = k.copy() 18 | k3.update(k2) 19 | return f(*(a+a2),**k3) 20 | return g 21 | 22 | def resource(*paths): 23 | return resource_py(os.path.join(*paths)) 24 | 25 | class _NamedTmpFile(object): 26 | def __init__(self,name,delete): 27 | self.name = name 28 | self.delete = delete 29 | def __del__(self): 30 | if self.delete: 31 | os.remove(self.name) 32 | 33 | def named_tmpfile(suffix='', prefix='tmp', dir=None, delete=True): 34 | '''The Windows version of tempfile.NamedTemporaryFile doesn't not work for the most 35 | common case, since Windows does not allow one to open the same file twice. Therefore, 36 | we implement our own, following Andre Pang's code from 37 | http://stackoverflow.com/questions/2549384/how-do-i-create-a-named-temporary-file-on-windows-in-python''' 38 | (file,name) = tempfile.mkstemp(prefix=prefix,suffix=suffix,dir=dir) 39 | os.close(file) 40 | return _NamedTmpFile(name,delete) 41 | -------------------------------------------------------------------------------- /geode/utility/base64.h: -------------------------------------------------------------------------------- 1 | // Base 64 encoding and decoding 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | GEODE_CORE_EXPORT string base64_encode(const string& src); 9 | GEODE_CORE_EXPORT string base64_encode(RawArray src); 10 | 11 | GEODE_CORE_EXPORT string base64_decode(const string& src); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /geode/utility/c_str.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Convert either const char* or string to const char* 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | using std::string; 10 | 11 | static inline const char* c_str(char* s) { 12 | return s; 13 | } 14 | 15 | static inline const char* c_str(const char* s) { 16 | return s; 17 | } 18 | 19 | static inline const char* c_str(const string& s) { 20 | return s.c_str(); 21 | } 22 | 23 | // Work for boost::filesystem::path 24 | template static inline const char* c_str(const T& s) { 25 | return c_str(s.string()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /geode/utility/const_cast.h: -------------------------------------------------------------------------------- 1 | /// A more convenient const_cast 2 | #pragma once 3 | 4 | namespace geode { 5 | 6 | template inline T& const_cast_(const T& x) { 7 | return const_cast(x); 8 | } 9 | 10 | template inline T* const_cast_(const T* x) { 11 | return const_cast(x); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /geode/utility/convert_case.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace geode { 7 | 8 | inline string to_lower(string const &S) { 9 | string s(S); 10 | for (auto &c : s) 11 | c = tolower(c); 12 | return s; 13 | } 14 | 15 | inline string to_upper(string const &s) { 16 | string S(s); 17 | for (auto &c : S) 18 | c = toupper(c); 19 | return S; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /geode/utility/curry.cpp: -------------------------------------------------------------------------------- 1 | // A simpler version of boost::bind 2 | 3 | #include 4 | namespace geode { 5 | 6 | namespace { 7 | 8 | struct A {}; 9 | 10 | struct B {}; 11 | 12 | struct C {}; 13 | 14 | C f(A,B) { 15 | return C(); 16 | } 17 | 18 | struct G { 19 | typedef C result_type; // For Windows 20 | 21 | C g(A,B) { 22 | return C(); 23 | } 24 | 25 | C h(A,B) const { 26 | return C(); 27 | } 28 | 29 | C operator()(A,B) const { 30 | return C(); 31 | } 32 | }; 33 | 34 | } 35 | 36 | GEODE_UNUSED static void curry_test() { 37 | G g; 38 | A a; 39 | B b; 40 | 41 | // Test free functions 42 | auto fa = curry(f,a); 43 | C(fa(b)); 44 | 45 | // Test nonconst member functions 46 | auto Gga = curry(&G::g,&g,a); 47 | C(Gga(b)); 48 | 49 | // Test const member functions 50 | auto Gha = curry(&G::h,const_cast(&g),a); 51 | C(Gha(b)); 52 | 53 | // Test function objects 54 | auto ga = curry(g,a); 55 | C(ga(b)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /geode/utility/from_string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | using std::string; 9 | 10 | template 11 | static bool from_string(T& t, const string& s) { 12 | // for some reason, this does not work on some systems 13 | std::istringstream iss(s); 14 | return !(iss >> t).fail(); 15 | } 16 | 17 | template <> 18 | inline bool from_string(real& t, const string& s) { 19 | const char* st = s.c_str(); 20 | char* ep; 21 | t = strtod(st, &ep); 22 | return st != ep; 23 | } 24 | 25 | template <> 26 | inline bool from_string(int& t, const string& s) { 27 | const char* st = s.c_str(); 28 | char* ep; 29 | long tt = strtol(st, &ep, 10); 30 | t = (int)tt; 31 | return st != ep && t==tt; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /geode/utility/function.h: -------------------------------------------------------------------------------- 1 | // function out of std:: 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace geode { 8 | using std::function; 9 | } // geode namespace 10 | -------------------------------------------------------------------------------- /geode/utility/interrupts.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // File interrupts 3 | //##################################################################### 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | static std::vector interrupt_checkers; 11 | 12 | void check_interrupts() { 13 | for (const auto checker : interrupt_checkers) 14 | checker(); 15 | } 16 | 17 | bool interrupted() { 18 | try { 19 | check_interrupts(); 20 | return false; 21 | } catch (...) { 22 | return true; 23 | } 24 | } 25 | 26 | void add_interrupt_checker(void (*checker)()) { 27 | interrupt_checkers.push_back(checker); 28 | } 29 | 30 | #ifdef GEODE_PYTHON 31 | void check_python_interrupts() { 32 | bool error = false; 33 | #pragma omp critical 34 | { 35 | if (PyErr_Occurred() || PyErr_CheckSignals()) 36 | error = true; 37 | } 38 | if (error) 39 | throw_python_error(); 40 | } 41 | #endif 42 | 43 | } 44 | -------------------------------------------------------------------------------- /geode/utility/interrupts.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // File interrupts 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | namespace geode { 8 | 9 | // Check if an interrupt has been posted, and throw an exception if so. 10 | // This function is OpenMP thread safe, but any exceptions thrown must 11 | // be caught if inside a parallel block (e.g., use interrupted() instead). 12 | GEODE_CORE_EXPORT void check_interrupts(); 13 | 14 | // Check if an interrupt has been posted without throwing an exception. 15 | // Internally, interrupt exceptions will be caught and squelched. 16 | // This function is OpenMP thread safe. 17 | GEODE_CORE_EXPORT bool interrupted(); 18 | 19 | // Add a function to call from check_interrupts. It must be safe to call 20 | // this function several times for the same interrupt, and checker 21 | // must be thread safe. 22 | GEODE_CORE_EXPORT void add_interrupt_checker(void (*checker)()); 23 | 24 | #ifdef GEODE_PYTHON 25 | // Interrupt checker for Python exceptions. Use only from geode/module.cpp. 26 | void check_python_interrupts(); 27 | #endif 28 | 29 | } 30 | -------------------------------------------------------------------------------- /geode/utility/move.h: -------------------------------------------------------------------------------- 1 | // Clang doesn't have the C++11 headers by default, so declare move and forward ourselves 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | // Mark an object as safely moveable 9 | template GEODE_ALWAYS_INLINE static inline typename remove_reference::type&& move(T&& x) { 10 | return static_cast::type&&>(x); 11 | } 12 | 13 | // For perfect forwarding 14 | template GEODE_ALWAYS_INLINE static inline T&& forward(typename remove_reference::type& x) GEODE_NOEXCEPT { 15 | return static_cast(x); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /geode/utility/mpl.h: -------------------------------------------------------------------------------- 1 | // Simple, standalone version of boost::mpl 2 | #pragma once 3 | 4 | #include 5 | namespace geode { 6 | namespace mpl { 7 | 8 | // Booleans 9 | template struct bool_ { static const bool value = b; }; 10 | typedef bool_ true_; 11 | typedef bool_ false_; 12 | 13 | // Ints 14 | template struct int_ { static const int value = i; }; 15 | 16 | // Logic 17 | template 18 | struct and_ : public bool_ {}; 19 | template 20 | struct or_ : public bool_ {}; 21 | template struct not_ : public bool_<(!A::value)> {}; 22 | 23 | // Conditionals 24 | template struct if_c; 25 | template struct if_c { typedef A type; }; 26 | template struct if_c { typedef B type; }; 27 | template struct if_ : public if_c<(C::value?true:false),A,B> {}; 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /geode/utility/pass.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Pass utility for variadic templates 3 | //##################################################################### 4 | // 5 | // See http://en.wikipedia.org/wiki/Variadic_template for details. Example usage: 6 | // 7 | // template void call_many(const F& f, Args&&... args) { 8 | // GEODE_PASS(f(args)); // Call f on each of the input arguments 9 | // } 10 | // 11 | //##################################################################### 12 | #pragma once 13 | 14 | #include 15 | namespace geode { 16 | 17 | #define GEODE_PASS(expression) {const int _pass_helper[] GEODE_UNUSED = {((expression),1)...};} 18 | 19 | } 20 | -------------------------------------------------------------------------------- /geode/utility/prioritize.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace geode { 6 | 7 | template 8 | struct Prioritize { 9 | A a; 10 | P p; 11 | 12 | Prioritize(A const &a, P const &p) 13 | : a(a), p(p) {} 14 | 15 | inline bool operator<(const Prioritize& b) const { 16 | return p < b.p; 17 | } 18 | 19 | inline bool operator>(const Prioritize& b) const { 20 | return p > b.p; 21 | } 22 | 23 | inline Prioritize &operator=(Prioritize const &b) { 24 | a = b.a; 25 | p = b.p; 26 | return *this; 27 | } 28 | }; 29 | 30 | template 31 | inline Prioritize prioritize(const A& a, const B& b) { 32 | return Prioritize(a, b); 33 | } 34 | 35 | template 36 | std::ostream &operator<<(std::ostream &os, Prioritize const &p) { 37 | return os << p.p << ":" << p.a; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /geode/utility/process.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Namespace process 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #ifndef _WIN32 9 | #include 10 | #endif 11 | namespace geode { 12 | namespace process { 13 | 14 | // CPU usage for (user,system) 15 | GEODE_CORE_EXPORT Vector cpu_times(); 16 | 17 | GEODE_CORE_EXPORT size_t memory_usage(); 18 | GEODE_CORE_EXPORT size_t max_memory_usage(); 19 | 20 | #ifdef _WIN32 21 | enum { 22 | FE_INVALID = 0x01, 23 | FE_DIVBYZERO = 0x04, 24 | FE_OVERFLOW = 0x08, 25 | FE_UNDERFLOW = 0x10, 26 | FE_INEXACT = 0x20 27 | }; 28 | #endif 29 | 30 | // Exceptions should be a combination of FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW, FE_UNDERFLOW 31 | GEODE_CORE_EXPORT void set_float_exceptions(const int exceptions=FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW); 32 | 33 | GEODE_CORE_EXPORT void backtrace(); 34 | GEODE_CORE_EXPORT void set_backtrace(const bool enable=true); 35 | GEODE_CORE_EXPORT void block_interrupts(const bool block=true); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /geode/utility/resource.h: -------------------------------------------------------------------------------- 1 | // Locate extra resource files (textures, etc.) at runtime 2 | #pragma once 3 | 4 | /* To use, install the resources in an SConscript via something like 5 | * 6 | * resource(env,"images") 7 | * 8 | * and look up individual files at runtime via something like 9 | * 10 | * string path = resource("images","metal.jpg"); 11 | */ 12 | 13 | #include 14 | namespace geode { 15 | 16 | using std::string; 17 | 18 | // Get the base path for resources 19 | GEODE_CORE_EXPORT string resource_path(); 20 | 21 | // Get the path to the given resource. Alias for path::join(resource_path(),path). 22 | GEODE_CORE_EXPORT string resource(const string& path); 23 | GEODE_CORE_EXPORT string resource(const string& path0, const string& path1); 24 | GEODE_CORE_EXPORT string resource(const string& path0, const string& path1, const string& path2); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /geode/utility/rounding.h: -------------------------------------------------------------------------------- 1 | // Floating point rounding mode control 2 | #pragma once 3 | 4 | #if !defined(_WIN32) || defined(__MINGW32__) 5 | #include 6 | #else 7 | #include 8 | #include 9 | #endif 10 | namespace geode { 11 | 12 | // We use the native API on posix, or emulate it on Windows. 13 | // These functions should not be called in performance critical loops. 14 | 15 | // Be careful when using fesetround as Clang can 'optimize' your code by moving 16 | // operations past the fesetround call and has no safe mechanism to prevent this. 17 | 18 | #if defined(_WIN32) && !defined(__MINGW32__) 19 | 20 | // Teach Windows that we care about floating point rounding modes 21 | #pragma fenv_access (on) 22 | 23 | enum { 24 | FE_TONEAREST = _RC_NEAR, 25 | FE_UPWARD = _RC_UP, 26 | FE_DOWNWARD = _RC_DOWN, 27 | FE_TOWARDZERO = _RC_CHOP 28 | }; 29 | 30 | static inline int fegetround() { 31 | return _controlfp(0,0) & _MCW_RC; 32 | } 33 | 34 | static inline int fesetround(int mode) { 35 | assert((mode&_MCW_RC)==mode); 36 | _controlfp(mode,_MCW_RC); 37 | return 0; // Always indicate success 38 | } 39 | 40 | #endif 41 | 42 | } 43 | -------------------------------------------------------------------------------- /geode/utility/str.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Stream based convertion from T to str 3 | //##################################################################### 4 | // 5 | // This is similar to boost::lexical_cast, but simpler and detects 6 | // operator<< overloads that exist only in the geode namespace. 7 | // 8 | //##################################################################### 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | namespace geode { 15 | 16 | using std::string; 17 | 18 | static inline string str() { 19 | return string(); 20 | } 21 | 22 | template string str(const T& x) { 23 | std::ostringstream os; 24 | os << x; 25 | return os.str(); 26 | } 27 | 28 | static inline string str(const string& x) { 29 | return x; 30 | } 31 | 32 | static inline string str(const char* x) { 33 | return x; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /geode/utility/stream.cpp: -------------------------------------------------------------------------------- 1 | // Stream I/O related utilities 2 | 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | void throw_unexpected_error(expect expected,char got) { 8 | throw ValueError(format("expected '%c' during stream input, got '%c'",expected.c,got)); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /geode/utility/stream.h: -------------------------------------------------------------------------------- 1 | // Stream I/O related utilities 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | using std::istream; 10 | 11 | struct expect { 12 | char c; 13 | expect(char c) 14 | :c(c) {} 15 | }; 16 | 17 | GEODE_CORE_EXPORT void GEODE_NORETURN(throw_unexpected_error(expect expected,char got)); 18 | 19 | inline istream& operator>>(istream& input, expect expected) { 20 | char got; 21 | input >> got; 22 | if (got != expected.c) 23 | throw_unexpected_error(expected,got); 24 | return input; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /geode/utility/time.cpp: -------------------------------------------------------------------------------- 1 | // Current time 2 | 3 | #include 4 | #if defined(_WIN32) 5 | #ifndef __MINGW32__ 6 | #pragma comment(lib, "winmm.lib") 7 | #endif 8 | #include 9 | #elif defined(__linux__) || defined(__CYGWIN__) || defined(__APPLE__) 10 | #include 11 | #include 12 | #endif 13 | namespace geode { 14 | 15 | // Windows 16 | #ifdef _WIN32 17 | 18 | static double get_resolution() { 19 | __int64 frequency; 20 | QueryPerformanceFrequency((LARGE_INTEGER*)&frequency); 21 | return 1./frequency; 22 | } 23 | static double resolution = get_resolution(); 24 | 25 | double get_time() { 26 | __int64 time; 27 | QueryPerformanceCounter((LARGE_INTEGER*)&time); 28 | return resolution*time; 29 | } 30 | 31 | // Unix 32 | #elif defined(__linux__) || defined(__CYGWIN__) || defined(__APPLE__) 33 | 34 | double get_time() { 35 | timeval tv; 36 | gettimeofday(&tv,0); 37 | return tv.tv_sec+1e-6*tv.tv_usec; 38 | } 39 | 40 | #else 41 | 42 | #error "Don't know how to get time on this platform" 43 | 44 | #endif 45 | 46 | } 47 | -------------------------------------------------------------------------------- /geode/utility/time.h: -------------------------------------------------------------------------------- 1 | // Current time 2 | #pragma once 3 | 4 | #include 5 | namespace geode { 6 | 7 | GEODE_CORE_EXPORT double get_time(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /geode/utility/tr1.h: -------------------------------------------------------------------------------- 1 | // Include unordered_set and unordered_map in the appropriate manner 2 | #pragma once 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace geode { 10 | 11 | using std::unordered_set; 12 | using std::unordered_map; 13 | using std::unordered_multiset; 14 | using std::unordered_multimap; 15 | 16 | } // namespace geode 17 | -------------------------------------------------------------------------------- /geode/utility/using.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define GEODE_USING_HELPER(name) using Base::name; 7 | #define GEODE_USING(...) GEODE_REMOVE_COMMAS(GEODE_MAP(GEODE_USING_HELPER,__VA_ARGS__)) 8 | -------------------------------------------------------------------------------- /geode/utility/validity.h: -------------------------------------------------------------------------------- 1 | // Check whether expressions are valid at compile time 2 | #pragma once 3 | 4 | // For example, we can check whether a type can be multiplied by two as follows: 5 | // 6 | // GEODE_VALIDITY_CHECKER(has_times_two,T,2*(*(T*)0)); 7 | // static_assert(has_times_two::value,""); 8 | // static_assert(!has_times_two::value,""); 9 | // 10 | // See http://stackoverflow.com/questions/2127693/sfinae-sizeof-detect-if-expression-compiles 11 | 12 | #include 13 | #include 14 | 15 | #define GEODE_VALIDITY_CHECKER(name,T,expression) \ 16 | template static char name##_helper(typename geode::First::type) { return 0; } /* success */ \ 17 | template static long name##_helper(...) { return 0; } /* failure */ \ 18 | template struct name : public geode::mpl::bool_(0))==1> {}; 19 | -------------------------------------------------------------------------------- /geode/value/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | Action.cpp 3 | Compute.cpp 4 | ConstValue.cpp 5 | Listen.cpp 6 | Prop.cpp 7 | PropManager.cpp 8 | Value.cpp 9 | ) 10 | 11 | set(module_HEADERS 12 | Action.h 13 | Compute.h 14 | ConstValue.h 15 | convert.h 16 | error_value.h 17 | extract.h 18 | forward.h 19 | link.h 20 | Listen.h 21 | Prop.h 22 | PropManager.h 23 | Value.h 24 | ) 25 | 26 | install_geode_headers(value ${module_HEADERS}) 27 | 28 | add_geode_module(value ${module_SRCS}) 29 | -------------------------------------------------------------------------------- /geode/value/ConstValue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace geode; 6 | 7 | void wrap_const_value() { 8 | python::function("const_value_py",const_value>); 9 | } 10 | -------------------------------------------------------------------------------- /geode/value/ConstValue.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class ConstValue 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template class ConstValue: public Value 11 | { 12 | public: 13 | GEODE_NEW_FRIEND 14 | typedef Value Base; 15 | private: 16 | ConstValue(const T& value, const string& name = string()) 17 | : Value(name) { 18 | this->set_value(value); 19 | } 20 | 21 | void update() const { 22 | GEODE_FATAL_ERROR(); // We never go invalid, so this should never be called 23 | } 24 | 25 | void dump(int indent) const { 26 | printf("%*sConstValue<%s>\n",2*indent,"",typeid(T).name()); 27 | } 28 | 29 | vector> dependencies() const { 30 | return vector>(); 31 | } 32 | }; 33 | 34 | template ValueRef const_value(const T& value, const string& name = string()) { 35 | return ValueRef(new_>(value,name)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /geode/value/Listen.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Listen 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | class Listen : public Object, public Action { 12 | public: 13 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 14 | typedef Object Base; 15 | private: 16 | Ref value; 17 | function f; 18 | 19 | GEODE_CORE_EXPORT Listen(const ValueBase& value, const function& f); 20 | public: 21 | ~Listen(); 22 | 23 | void input_changed() const; 24 | }; 25 | 26 | 27 | class BatchListen : public Object, public Action { 28 | public: 29 | GEODE_DECLARE_TYPE(GEODE_CORE_EXPORT) 30 | typedef Object Base; 31 | private: 32 | vector> values; 33 | function f; 34 | 35 | GEODE_CORE_EXPORT BatchListen(const vector>& values, const function& f); 36 | public: 37 | ~BatchListen(); 38 | 39 | void input_changed() const; 40 | }; 41 | 42 | GEODE_CORE_EXPORT Ref listen(const ValueBase& value, const function& f); 43 | GEODE_CORE_EXPORT Ref batch_listen(const vector>& values, const function& f); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /geode/value/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from geode import * 4 | from . import parser 5 | import types 6 | 7 | def is_value(value): 8 | return isinstance(value, Value) 9 | 10 | def is_prop(prop): 11 | return is_value(prop) and prop.is_prop() 12 | 13 | def const_value(value, name=""): 14 | return const_value_py(value, name) 15 | 16 | def Prop(name,default,shape=None): 17 | if shape is None: 18 | return make_prop(name,default) 19 | return make_prop_shape(name,default,shape) 20 | 21 | class cache_method(object): 22 | '''Decorator to cache a class method per instance. The equivalent of 'cache' in the function case.''' 23 | def __init__(self,f): 24 | self._name = '__'+f.__name__ 25 | self.f = f 26 | def __get__(self,instance,owner): 27 | try: 28 | return getattr(instance,self._name) 29 | except AttributeError: 30 | if type(instance)==types.InstanceType: 31 | raise TypeError('cache_method can only be used on new-style classes (must inherit from object)') 32 | value = cache(types.MethodType(self.f,instance,owner)) 33 | object.__setattr__(instance,self._name,value) 34 | return value 35 | 36 | def cache_named(name): 37 | def inner(f): 38 | return cache_named_inner(f, name) 39 | return inner 40 | -------------------------------------------------------------------------------- /geode/value/convert.h: -------------------------------------------------------------------------------- 1 | // Conversion from PyObject* to Value 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | #ifdef GEODE_PYTHON 12 | 13 | template static T convert_helper(const ValueRef>& value) { 14 | Ptr<> v = value(); 15 | return try_from_python(v ? v.get() : Py_None); 16 | } 17 | 18 | template struct FromPython>>{static Ref> convert(PyObject* object) { 19 | const ValueBase& base = from_python(object); 20 | if (const Value* exact = base.cast()) 21 | return geode::ref(*exact); 22 | if (const Value>* python = base.cast>()) 23 | return cache(convert_helper,ValueRef>(*python)).self; 24 | throw TypeError(format("can't convert '%s' to '%s'",typeid(base).name(),typeid(Value).name())); 25 | }}; 26 | 27 | template struct FromPython>>{static Ref> convert(PyObject* object) { 28 | return FromPython>>::convert(object).const_cast_(); 29 | }}; 30 | 31 | template struct FromPython>{static ValueRef convert(PyObject* object) { 32 | return *FromPython>>::convert(object); 33 | }}; 34 | 35 | #endif 36 | } 37 | -------------------------------------------------------------------------------- /geode/value/error_value.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function error_value 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template class ErrorValue : public Value { 11 | public: 12 | GEODE_NEW_FRIEND 13 | typedef Value Base; 14 | private: 15 | ExceptionValue error; 16 | 17 | ErrorValue(const exception& error) 18 | : error(error) {} 19 | 20 | void update() const { 21 | error.throw_(); 22 | } 23 | 24 | void dump(int indent) const { 25 | printf("%*sErrorValue<%s>\n",2*indent,"",typeid(T).name()); 26 | } 27 | }; 28 | 29 | // Compute a value that always throws the given exception 30 | template static inline ValueRef error_value(const exception& error) { 31 | return ValueRef(new_ >(error)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /geode/value/extract.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function extract 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | namespace geode { 10 | 11 | template static inline auto extract_helper(const ValueRef& value) 12 | -> decltype(value().template get()) { 13 | return value().template get(); 14 | } 15 | 16 | template static inline auto extract_helper(const ValueRef& value, int n) 17 | -> decltype(value()[n]) { 18 | auto& array = value(); 19 | GEODE_ASSERT(n<(int)array.size()); 20 | return array[n]; 21 | } 22 | 23 | // Extract the nth element of a tuple value as a value 24 | template static inline auto extract(const ValueRef& value) 25 | -> ValueRef())>::type> { 26 | typedef decltype(value().template get()) T; 27 | return cache(static_cast&)>(extract_helper),value); 28 | } 29 | 30 | // Extract the nth element of an array value as a value 31 | template static inline auto extract(const ValueRef& value, int n) 32 | -> ValueRef::type> { 33 | GEODE_ASSERT(n>=0); 34 | return cache(extract_helper,value,n); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /geode/value/forward.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace geode { 5 | 6 | class ValueBase; 7 | class PropBase; 8 | template class Value; 9 | template class ValueRef; 10 | class Action; 11 | template class Prop; 12 | template class PropRef; 13 | class Listen; 14 | class PropManager; 15 | 16 | template struct has_clamp : public mpl::false_{}; 17 | template<> struct has_clamp : public mpl::true_{}; 18 | template<> struct has_clamp : public mpl::true_{}; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /geode/value/link.h: -------------------------------------------------------------------------------- 1 | // Link two properties together: when one changes, the other will 2 | #pragma once 3 | 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | class PropLink : public Object { 9 | public: 10 | GEODE_NEW_FRIEND 11 | typedef Object Base; 12 | 13 | private: 14 | const Ref<> x,y,lx,ly; 15 | 16 | template PropLink(const PropRef& x, const PropRef& y) 17 | : x(x.self) 18 | , y(y.self) 19 | , lx(listen(x,curry(&PropLink::update,&*y,&*x))) 20 | , ly(listen(y,curry(&PropLink::update,&*x,&*y))) {} 21 | 22 | template static void update(Prop* dst, Prop* src) { 23 | dst->set((*src)()); 24 | } 25 | }; 26 | 27 | template Ref<> link(const PropRef& x, const PropRef& y) { 28 | return new_(x,y); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /geode/value/module.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace geode; 3 | 4 | void wrap_value() { 5 | GEODE_WRAP(value_base) 6 | GEODE_WRAP(prop) 7 | GEODE_WRAP(prop_manager) 8 | GEODE_WRAP(compute) 9 | GEODE_WRAP(listen) 10 | GEODE_WRAP(const_value) 11 | } 12 | -------------------------------------------------------------------------------- /geode/vector/ArithmeticPolicy.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header ArithmeticPolicy 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | template struct Sum{typedef decltype(declval()+declval()) type;}; 11 | template struct Product{typedef decltype(declval()*declval()) type;}; 12 | 13 | template struct Transpose{typedef decltype(declval().tranposed()) type;}; 14 | template struct ProductTranspose{typedef decltype(declval()*declval().transposed()) type;}; 15 | template struct TransposeProduct{typedef decltype(declval().transposed()*declval()) type;}; 16 | 17 | template struct ProductTranspose,UpperTriangularMatrix> { typedef Matrix type; }; 18 | template struct ProductTranspose,Matrix> { typedef Matrix type; }; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /geode/vector/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(module_SRCS 2 | blas.cpp 3 | Frame.cpp 4 | group.cpp 5 | Matrix2x2.cpp 6 | Matrix3x2.cpp 7 | Matrix3x3.cpp 8 | Matrix4x4.cpp 9 | Matrix.cpp 10 | Register.cpp 11 | Rotation.cpp 12 | SolidMatrix.cpp 13 | SparseMatrix.cpp 14 | SymmetricMatrix3x3.cpp 15 | TetrahedralGroup.cpp 16 | Vector.cpp 17 | ) 18 | 19 | set(module_HEADERS 20 | ArithmeticPolicy.h 21 | blas.h 22 | complex.h 23 | convert.h 24 | DiagonalMatrix2x2.h 25 | DiagonalMatrix3x3.h 26 | DiagonalMatrix.h 27 | Dot.h 28 | forward.h 29 | Frame.h 30 | group.h 31 | magnitude.h 32 | Matrix0x0.h 33 | Matrix1x1.h 34 | Matrix2x2.h 35 | Matrix3x2.h 36 | Matrix3x3.h 37 | Matrix4x4.h 38 | Matrix.h 39 | normalize.h 40 | Quaternion.h 41 | Register.h 42 | relative_error.h 43 | Rotation.h 44 | ScalarPolicy.h 45 | SolidMatrix.h 46 | SparseMatrix.h 47 | SymmetricMatrix2x2.h 48 | SymmetricMatrix3x3.h 49 | SymmetricMatrix.h 50 | TetrahedralGroup.h 51 | Twist.h 52 | UpperTriangularMatrix2x2.h 53 | UpperTriangularMatrix3x3.h 54 | UpperTriangularMatrix.h 55 | Vector0d.h 56 | Vector1d.h 57 | Vector2d.h 58 | Vector3d.h 59 | Vector4d.h 60 | Vector.h 61 | VectorPolicy.h 62 | ) 63 | 64 | install_geode_headers(vector ${module_HEADERS}) 65 | 66 | add_geode_module(vector ${module_SRCS}) 67 | -------------------------------------------------------------------------------- /geode/vector/DiagonalMatrix.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class DiagonalMatrix 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | -------------------------------------------------------------------------------- /geode/vector/Dot.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function Dot 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template class Vector; 9 | 10 | static inline float dot(const float a1,const float a2) 11 | {return a1*a2;} 12 | 13 | static inline double dot(const double a1,const double a2) 14 | {return a1*a2;} 15 | 16 | template 17 | static inline double dot_double_precision(const Vector& v1,const Vector& v2) 18 | {return dot(v1,v2);} 19 | 20 | static inline double dot_double_precision(const float a1,const float a2) 21 | {return a1*a2;} 22 | 23 | static inline double dot_double_precision(const double a1,const double a2) 24 | {return a1*a2;} 25 | 26 | } 27 | -------------------------------------------------------------------------------- /geode/vector/Register.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header Register 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | namespace geode { 11 | 12 | GEODE_CORE_EXPORT Frame> rigid_register(RawArray> X0, RawArray> X1, RawArray mass = RawArray()); 13 | GEODE_CORE_EXPORT Frame> rigid_register(RawArray> X0, RawArray> X1, RawArray mass = RawArray()); 14 | 15 | // Find the best affine transform from X0 to X1. Warning: undetermined problems will give poor results. 16 | GEODE_CORE_EXPORT Matrix affine_register(RawArray> X0, RawArray> X1, RawArray mass = RawArray()); 17 | GEODE_CORE_EXPORT Matrix affine_register(RawArray> X0, RawArray> X1, RawArray mass = RawArray()); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /geode/vector/SymmetricMatrix.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class SymmetricMatrix 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | -------------------------------------------------------------------------------- /geode/vector/UpperTriangularMatrix.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class UpperTriangularMatrix 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | -------------------------------------------------------------------------------- /geode/vector/Vector.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Class Vector 3 | //##################################################################### 4 | #include 5 | 6 | namespace geode { 7 | 8 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,2,int) 9 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,3,int) 10 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,4,int) 11 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,2,long) 12 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,3,long) 13 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,4,long) 14 | 15 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,2,short int) 16 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,3,short int) 17 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,4,short int) 18 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,1,float) 19 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,2,float) 20 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,3,float) 21 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,4,float) 22 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,1,double) 23 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,2,double) 24 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,3,double) 25 | GEODE_DEFINE_VECTOR_CONVERSIONS(GEODE_CORE_EXPORT,4,double) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /geode/vector/blas.cpp: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Header blas 3 | //##################################################################### 4 | #include "blas.h" 5 | #ifdef GEODE_BLAS 6 | #include 7 | #ifdef GEODE_MKL 8 | #define ILAENV ::ilaenv 9 | #else 10 | extern "C" { 11 | #ifndef __APPLE__ 12 | extern int ilaenv_(int*,char*,char*,int*,int*,int*,int*); 13 | #endif 14 | } 15 | #define ILAENV ::ilaenv_ 16 | #endif 17 | namespace geode { 18 | 19 | template int ilaenv(int ispec,const char* name,const char* opts,int m,int n) 20 | { 21 | char xname[20]; 22 | xname[0] = is_same::value?'s':'d'; 23 | strcpy(xname+1,name); 24 | #ifndef __APPLE__ 25 | int no = -1; 26 | return ILAENV(&ispec,xname,(char*)opts,&m,&n,&no,&no); 27 | #else 28 | GEODE_NOT_IMPLEMENTED(); 29 | #endif 30 | } 31 | 32 | #ifdef GEODE_PYTHON 33 | CBLAS_TRANSPOSE FromPython::convert(PyObject* object) { 34 | const char* s = from_python(object); 35 | switch (s[0]?s[1]?0:s[0]:0){ 36 | case 'n': case 'N': return CblasNoTrans; 37 | case 't': case 'T': return CblasTrans; 38 | default: throw ValueError("expected n or t (or N or T)");} 39 | } 40 | #endif 41 | 42 | template int ilaenv(int,const char*,const char*,int,int); 43 | template int ilaenv(int,const char*,const char*,int,int); 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /geode/vector/convert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | namespace geode { 7 | 8 | #ifdef GEODE_PYTHON 9 | 10 | // In other to instantiate a Vector conversion, place GEODE_DECLARE_VECTOR_CONVERSIONS (see vector/forward.h) 11 | // in a header and GEODE_DEFINE_VECTOR_CONVERSIONS in a .cpp. 12 | #define GEODE_DEFINE_VECTOR_CONVERSIONS(EXPORT,d,...) \ 13 | static_assert(NumpyIsStatic<__VA_ARGS__>::value,""); \ 14 | PyObject* to_python(const Vector<__VA_ARGS__,d>& v) { return to_numpy(v); } \ 15 | Vector<__VA_ARGS__,d> FromPython>::convert(PyObject* o) { return from_numpy>(o); } 16 | 17 | // To python conversion for arbitrary vectors 18 | template typename enable_if, PyObject*>::type to_python(const Vector& v) { 19 | static_assert(!NumpyIsStatic::value,"Numpy compatible types should use GEODE_DECLARE/DEFINE_VECTOR_CONVERSIONS"); 20 | PyObject *o[d]={0},*tuple=0; 21 | for (int i=0;i octahedral_group[24] = {%s};'%','.join('Q(%s)'%','.join(map(nice,r.sv)) for r in octahedral_group) 36 | -------------------------------------------------------------------------------- /geode/vector/group.cpp: -------------------------------------------------------------------------------- 1 | // Various groups 2 | 3 | #include 4 | #include 5 | namespace geode { 6 | 7 | typedef real T; 8 | typedef Vector TV; 9 | 10 | const T s = sqrt(.5); 11 | #define Q Rotation::from_components 12 | 13 | // Generated by group-helper: DO NOT EDIT 14 | const Rotation octahedral_group[24] = {Q(1,0,0,0),Q(0,1,0,0),Q(s,s,0,0),Q(s,-s,0,0),Q(0,0,1,0),Q(0,0,0,1),Q(0,0,s,s),Q(0,0,-s,s),Q(0,s,s,0),Q(s,0,0,s),Q(.5,.5,.5,.5),Q(.5,-.5,-.5,.5),Q(s,0,0,-s),Q(0,-s,s,0),Q(-.5,-.5,.5,.5),Q(-.5,.5,-.5,.5),Q(-.5,.5,.5,.5),Q(.5,.5,-.5,.5),Q(s,0,-s,0),Q(0,s,0,s),Q(-.5,-.5,-.5,.5),Q(.5,-.5,.5,.5),Q(s,0,s,0),Q(0,-s,0,s)}; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /geode/vector/group.h: -------------------------------------------------------------------------------- 1 | // Various groups 2 | #pragma once 3 | 4 | #include 5 | namespace geode { 6 | 7 | // Rotational symmetries of the cube 8 | extern GEODE_CORE_EXPORT const Rotation> octahedral_group[24]; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /geode/vector/magnitude.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function Magnitude 3 | //##################################################################### 4 | #pragma once 5 | 6 | #include 7 | #include 8 | namespace geode { 9 | 10 | using ::std::abs; 11 | 12 | template 13 | inline typename TV::Scalar magnitude(const TV& v) 14 | {return v.magnitude();} 15 | 16 | template 17 | inline typename TV::Scalar sqr_magnitude(const TV& v) 18 | {return v.sqr_magnitude();} 19 | 20 | inline int magnitude(const int a) 21 | {return abs(a);} 22 | 23 | inline float magnitude(const float a) 24 | {return abs(a);} 25 | 26 | inline double magnitude(const double a) 27 | {return abs(a);} 28 | 29 | inline float sqr_magnitude(const float a) 30 | {return a*a;} 31 | 32 | inline double sqr_magnitude(const double a) 33 | {return a*a;} 34 | 35 | } 36 | -------------------------------------------------------------------------------- /geode/vector/normalize.h: -------------------------------------------------------------------------------- 1 | //##################################################################### 2 | // Function Normalize 3 | //##################################################################### 4 | #pragma once 5 | 6 | namespace geode { 7 | 8 | template 9 | inline typename T::Scalar normalize(T& v) 10 | {return v.normalize();} 11 | 12 | template 13 | inline T normalized(const T& v) 14 | {return v.normalized();} 15 | 16 | inline float normalize(float& a) 17 | {float a_save=a; 18 | if(a>=0){a=1;return a_save;} 19 | else{a=-1;return -a_save;}} 20 | 21 | inline double normalize(double& a) 22 | {double a_save=a; 23 | if(a>=0){a=1;return a_save;} 24 | else{a=-1;return -a_save;}} 25 | 26 | inline float normalized(const float a) 27 | {return a>=0?(float)1:(float)-1;} 28 | 29 | inline double normalized(const double a) 30 | {return a>=0?(double)1:(double)-1;} 31 | 32 | } 33 | -------------------------------------------------------------------------------- /geode/vector/relative_error.h: -------------------------------------------------------------------------------- 1 | // relative_error function 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | namespace geode { 8 | 9 | template typename enable_if,T>::type relative_error(const T& a, const T& b, const T& absolute=1e-30) { 10 | return abs(a-b)/max(abs(a),abs(b),absolute); 11 | } 12 | 13 | template typename TV::Scalar relative_error(const TV& a, const TV& b, const typename TV::Scalar absolute=1e-30) { 14 | return (a-b).maxabs()/max(a.maxabs(),b.maxabs(),absolute); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /geode/vector/test_register.py: -------------------------------------------------------------------------------- 1 | from geode.vector import * 2 | from numpy import * 3 | 4 | def test_register(): 5 | random.seed(217301) 6 | for _ in xrange(10): 7 | for d in 2,3: 8 | X0 = random.randn(10,d) 9 | t = random.randn(d) 10 | A = random.randn(d,d) 11 | r,_ = linalg.qr(A) 12 | if linalg.det(r)<0: 13 | r[0] = -r[0] 14 | X1 = t + Matrix(r)*X0 15 | X2 = t + Matrix(A)*X0 16 | f = rigid_register(X0,X1) 17 | B = affine_register(X0,X2) 18 | assert relative_error(t,f.t) < 1e-5 19 | assert relative_error(r,f.r.matrix()) < 1e-5 20 | assert relative_error(t,B[:d,d]) < 1e-5 21 | assert relative_error(A,B[:d,:d]) < 1e-5 22 | assert all(B[d]==hstack([zeros(d),1])) 23 | -------------------------------------------------------------------------------- /metaBuild.sh: -------------------------------------------------------------------------------- 1 | DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 2 | ARG1="$1" 3 | shift 4 | CMAKE_ARGS=$@ 5 | echo "CMAKE_ARGS: ${CMAKE_ARGS}" 6 | if [ "${ARG1}" = "debug" ]; then 7 | CMAKE_ARGS+=" -DCMAKE_BUILD_TYPE=Debug " 8 | elif [ "${ARG1}" = "release" ]; then 9 | CMAKE_ARGS+=" -DCMAKE_BUILD_TYPE=Release " 10 | elif [ "${ARG1}" = "clean" ]; then 11 | (cd "${DIR}/build" && make clean) 12 | exit 0 13 | else 14 | echo "Missing or unrecognized metabuild argument \"${ARG1}\"" 15 | exit 1 16 | fi 17 | 18 | DIR_3RD_PARTY="${DIR}/../" 19 | CMAKE_ARGS+=" -DGMP_LIB_DIR=${DIR_3RD_PARTY}/mpir/.libs/ " 20 | CMAKE_ARGS+=" -DGMP_INCLUDE_DIR=${DIR_3RD_PARTY}/mpir/ " 21 | CMAKE_ARGS+=" -DCMAKE_VERBOSE_MAKEFILE=On " 22 | 23 | SYSTEM_NAME=`uname -s` 24 | # Platform specific config 25 | # So far I've only tested this on one OSX machine. This will probably require additional tweaking for Linux and Windows 26 | if [ "$SYSTEM_NAME" = "Darwin" ]; then 27 | PKG_CONFIG_PATH="/System/Library/Frameworks/Python.framework/Versions/2.7/lib/pkgconfig:${PKG_CONFIG_PATH}" 28 | fi 29 | # 30 | set -x 31 | (cd ${DIR} && (mkdir build; cd build && PKG_CONFIG_PATH=${PKG_CONFIG_PATH} cmake $CMAKE_ARGS ../ && make)) 32 | -------------------------------------------------------------------------------- /metabuild_scripts/common_geode_build.sh: -------------------------------------------------------------------------------- 1 | 2 | chek_dir() 3 | { 4 | if [ ! -f "GeodeSupport.cmake" ] 5 | then 6 | echo "run from top level directory" 7 | exit 8 | fi 9 | return $(pwd) 10 | } 11 | 12 | clean_build_dir() 13 | { 14 | if [ -a "build" ] 15 | then 16 | echo "removing previous build directory" 17 | rm -rf build 18 | fi 19 | echo "creating new build directory" 20 | mkdir build 21 | } 22 | 23 | build_cmake() 24 | { 25 | cmake ../ 26 | } 27 | 28 | build_make() 29 | { 30 | 31 | NPROCS=1 32 | OS=$(uname -s) 33 | if [[ $OS == *"Linux"* ]] 34 | then 35 | NPROCS=$(grep -c ^processor /proc/cpuinfo) 36 | fi 37 | 38 | if [[ $OS == *"Darwin"* ]] # Assume Mac OS X 39 | then 40 | NPROCS=$(sysctl -n hw.ncpu) 41 | fi 42 | 43 | make -j $NPROCS 44 | } 45 | 46 | build_phase() 47 | { 48 | cd build 49 | build_cmake 50 | build_make 51 | cd .. 52 | } 53 | 54 | -------------------------------------------------------------------------------- /metabuild_scripts/macos_clang_38.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f "GeodeSupport.cmake" ] 4 | then 5 | echo "run from top level directory" 6 | exit 7 | fi 8 | 9 | source metabuild_scripts/common_geode_build.sh 10 | 11 | 12 | # C++ things 13 | export CXX="clang++-3.8 -stdlib=libc++" 14 | export CXXFLAGS="$CXXFLAGS -std=c++1y -I/usr/local/opt/llvm38/lib/llvm-3.8/include/c++/v1 " 15 | export LDFLAGS="$LDFLAGS -L/usr/local/opt/llvm38/lib/llvm-3.8/lib " 16 | 17 | clean_build_dir 18 | 19 | build_phase 20 | 21 | 22 | -------------------------------------------------------------------------------- /metabuild_scripts/macos_default.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f "GeodeSupport.cmake" ] 4 | then 5 | echo "run from top level directory" 6 | exit 7 | fi 8 | 9 | source metabuild_scripts/Common_geode_build.sh 10 | 11 | # C++ things 12 | export CXX="/usr/bin/g++ " 13 | export CXXFLAGS="$CXXFLAGS -std=c++0x " 14 | export LDFLAGS="$LDFLAGS " 15 | 16 | clean_build_dir 17 | 18 | build_phase 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_clang_35.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-3.5 4 | export CXX=clang++-3.5 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_clang_36.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-3.6 4 | export CXX=clang++-3.6 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_clang_37.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-3.7 4 | export CXX=clang++-3.7 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_clang_38.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f "GeodeSupport.cmake" ] 4 | then 5 | echo "run from top level directory" 6 | exit 7 | fi 8 | 9 | source metabuild_scripts/common_geode_build.sh 10 | 11 | # C++ things 12 | export CC=clang-3.8 13 | export CXX=clang++-3.8 14 | export CXXFLAGS="$CXXFLAGS -std=c++1y " 15 | 16 | clean_build_dir 17 | 18 | build_phase 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_clang_39.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=clang-3.9 4 | export CXX=clang++-3.9 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_gcc_474.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-4.7 4 | export CXX=g++-4.7 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_gcc_541.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | if [ ! -f "GeodeSupport.cmake" ] 5 | then 6 | echo "run from top level directory" 7 | exit 8 | fi 9 | 10 | source metabuild_scripts/common_geode_build.sh 11 | 12 | # C++ things 13 | export CC=gcc-5 14 | export CXX=g++-5 15 | 16 | clean_build_dir 17 | 18 | build_phase 19 | 20 | 21 | -------------------------------------------------------------------------------- /metabuild_scripts/ubuntu_1604_gcc_620.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CC=gcc-6 4 | export CXX=g++-6 5 | 6 | if [ ! -f "GeodeSupport.cmake" ] 7 | then 8 | echo "run from top level directory" 9 | exit 10 | fi 11 | 12 | source metabuild_scripts/common_geode_build.sh 13 | 14 | clean_build_dir 15 | 16 | 17 | build_phase 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.10.1 2 | scipy==0.16.1 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [pytest] 2 | minversion = 2.1 3 | norecursedirs = .* build dist site_scons output* 4 | addopts = -v --tb=short --doctest-glob='' 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup,find_packages 4 | 5 | setup( 6 | # Basics 7 | name='geode', 8 | version='0.0-dev', 9 | description='A computational geometry library', 10 | author='Otherlab et al.', 11 | author_email='geode-dev@googlegroups.com', 12 | url='http://github.com/otherlab/geode', 13 | 14 | # Installation 15 | packages=find_packages(), 16 | package_data={'geode':['*.py','*.so'], 'gui': ['*.py', '*.so']}, 17 | ) 18 | --------------------------------------------------------------------------------