toxiclibs 0.2-java → 0.5.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +16 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE +675 -0
- data/README.md +12 -5
- data/Rakefile +25 -82
- data/examples/attract_repel/attract_repel.rb +30 -0
- data/examples/attract_repel/attractor.rb +23 -0
- data/examples/attract_repel/particle.rb +27 -0
- data/examples/data/ti_yong.png +0 -0
- data/examples/force_directed/cluster.rb +76 -0
- data/examples/force_directed/force_directed_graph.rb +92 -0
- data/examples/force_directed/node.rb +26 -0
- data/examples/gray_scott_image.rb +75 -0
- data/examples/gray_scott_tone_map.rb +77 -0
- data/examples/implicit.rb +139 -0
- data/examples/inflate_mesh.rb +89 -0
- data/examples/model_align.rb +44 -0
- data/examples/povmesh/ftest.rb +46 -0
- data/examples/povmesh/tentacle.rb +73 -0
- data/examples/simple_cluster/cluster.rb +47 -0
- data/examples/simple_cluster/node.rb +27 -0
- data/examples/simple_cluster/simple_cluster.rb +60 -0
- data/examples/soft_body/blanket.rb +45 -0
- data/examples/soft_body/connection.rb +16 -0
- data/examples/soft_body/particle.rb +22 -0
- data/examples/soft_body/soft_body_square_adapted.rb +55 -0
- data/lib/toxiclibs.jar +0 -0
- data/lib/toxiclibs.rb +91 -32
- data/lib/toxiclibs/version.rb +1 -1
- data/pom.xml +122 -0
- data/src/com/toxi/net/ClientListener.java +41 -0
- data/src/com/toxi/net/ServerListener.java +70 -0
- data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
- data/src/com/toxi/net/ServerState.java +18 -0
- data/src/com/toxi/net/UDPConnection.java +66 -0
- data/src/com/toxi/net/UDPSyncClient.java +81 -0
- data/src/com/toxi/net/UDPSyncServer.java +450 -0
- data/src/com/toxi/nio/UDPClient.java +121 -0
- data/src/com/toxi/nio/UDPClientState.java +32 -0
- data/src/com/toxi/nio/UDPServer.java +129 -0
- data/src/toxi/color/AccessCriteria.java +114 -0
- data/src/toxi/color/AlphaAccessor.java +67 -0
- data/src/toxi/color/CMYKAccessor.java +122 -0
- data/src/toxi/color/CMYKDistanceProxy.java +40 -0
- data/src/toxi/color/ColorGradient.java +260 -0
- data/src/toxi/color/ColorList.java +699 -0
- data/src/toxi/color/ColorRange.java +671 -0
- data/src/toxi/color/ColorTheme.java +163 -0
- data/src/toxi/color/DistanceProxy.java +44 -0
- data/src/toxi/color/HSVAccessor.java +113 -0
- data/src/toxi/color/HSVDistanceProxy.java +40 -0
- data/src/toxi/color/HistEntry.java +85 -0
- data/src/toxi/color/Histogram.java +185 -0
- data/src/toxi/color/Hue.java +249 -0
- data/src/toxi/color/LuminanceAccessor.java +78 -0
- data/src/toxi/color/NamedColor.java +935 -0
- data/src/toxi/color/ProximityComparator.java +70 -0
- data/src/toxi/color/RGBAccessor.java +113 -0
- data/src/toxi/color/RGBDistanceProxy.java +41 -0
- data/src/toxi/color/ReadonlyTColor.java +296 -0
- data/src/toxi/color/TColor.java +1677 -0
- data/src/toxi/color/TColorAdapter.java +68 -0
- data/src/toxi/color/ToneMap.java +218 -0
- data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
- data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
- data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
- data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
- data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
- data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
- data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
- data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
- data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
- data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
- data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
- data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
- data/src/toxi/data/csv/CSVAdapter.java +74 -0
- data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
- data/src/toxi/data/csv/CSVListener.java +61 -0
- data/src/toxi/data/csv/CSVParser.java +202 -0
- data/src/toxi/data/feeds/AtomAuthor.java +49 -0
- data/src/toxi/data/feeds/AtomContent.java +50 -0
- data/src/toxi/data/feeds/AtomEntry.java +111 -0
- data/src/toxi/data/feeds/AtomFeed.java +129 -0
- data/src/toxi/data/feeds/AtomLink.java +62 -0
- data/src/toxi/data/feeds/RSSChannel.java +88 -0
- data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
- data/src/toxi/data/feeds/RSSFeed.java +99 -0
- data/src/toxi/data/feeds/RSSItem.java +104 -0
- data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
- data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
- data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
- data/src/toxi/geom/AABB.java +658 -0
- data/src/toxi/geom/Axis3D.java +116 -0
- data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
- data/src/toxi/geom/BernsteinPolynomial.java +94 -0
- data/src/toxi/geom/BezierCurve2D.java +159 -0
- data/src/toxi/geom/BezierCurve3D.java +148 -0
- data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
- data/src/toxi/geom/BoxIntersector.java +52 -0
- data/src/toxi/geom/Circle.java +230 -0
- data/src/toxi/geom/CircleIntersector.java +85 -0
- data/src/toxi/geom/Cone.java +150 -0
- data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
- data/src/toxi/geom/CoordinateExtractor.java +16 -0
- data/src/toxi/geom/Ellipse.java +250 -0
- data/src/toxi/geom/GMatrix.java +2599 -0
- data/src/toxi/geom/GVector.java +833 -0
- data/src/toxi/geom/GlobalGridTesselator.java +54 -0
- data/src/toxi/geom/GridTesselator.java +108 -0
- data/src/toxi/geom/Intersector2D.java +49 -0
- data/src/toxi/geom/Intersector3D.java +51 -0
- data/src/toxi/geom/IsectData2D.java +103 -0
- data/src/toxi/geom/IsectData3D.java +103 -0
- data/src/toxi/geom/Line2D.java +534 -0
- data/src/toxi/geom/Line3D.java +471 -0
- data/src/toxi/geom/LineStrip2D.java +430 -0
- data/src/toxi/geom/LineStrip3D.java +230 -0
- data/src/toxi/geom/LocalGridTesselator.java +57 -0
- data/src/toxi/geom/Matrix3d.java +3048 -0
- data/src/toxi/geom/Matrix4f.java +3446 -0
- data/src/toxi/geom/Matrix4x4.java +1076 -0
- data/src/toxi/geom/MatrixSizeException.java +58 -0
- data/src/toxi/geom/OctreeVisitor.java +44 -0
- data/src/toxi/geom/Origin3D.java +148 -0
- data/src/toxi/geom/Plane.java +293 -0
- data/src/toxi/geom/PlaneIntersector.java +57 -0
- data/src/toxi/geom/PointCloud3D.java +253 -0
- data/src/toxi/geom/PointOctree.java +502 -0
- data/src/toxi/geom/PointQuadtree.java +375 -0
- data/src/toxi/geom/Polygon2D.java +1038 -0
- data/src/toxi/geom/PolygonClipper2D.java +45 -0
- data/src/toxi/geom/PolygonTesselator.java +20 -0
- data/src/toxi/geom/QuadtreeVisitor.java +44 -0
- data/src/toxi/geom/Quaternion.java +641 -0
- data/src/toxi/geom/Ray2D.java +146 -0
- data/src/toxi/geom/Ray3D.java +150 -0
- data/src/toxi/geom/Ray3DIntersector.java +75 -0
- data/src/toxi/geom/ReadonlyVec2D.java +575 -0
- data/src/toxi/geom/ReadonlyVec3D.java +628 -0
- data/src/toxi/geom/ReadonlyVec4D.java +431 -0
- data/src/toxi/geom/Rect.java +720 -0
- data/src/toxi/geom/Reflector3D.java +58 -0
- data/src/toxi/geom/Shape2D.java +94 -0
- data/src/toxi/geom/Shape3D.java +42 -0
- data/src/toxi/geom/SingularMatrixException.java +57 -0
- data/src/toxi/geom/SpatialBins.java +182 -0
- data/src/toxi/geom/SpatialIndex.java +61 -0
- data/src/toxi/geom/Sphere.java +224 -0
- data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
- data/src/toxi/geom/Spline2D.java +349 -0
- data/src/toxi/geom/Spline3D.java +351 -0
- data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
- data/src/toxi/geom/Triangle2D.java +422 -0
- data/src/toxi/geom/Triangle3D.java +456 -0
- data/src/toxi/geom/TriangleIntersector.java +105 -0
- data/src/toxi/geom/Vec2D.java +1328 -0
- data/src/toxi/geom/Vec3D.java +1832 -0
- data/src/toxi/geom/Vec4D.java +985 -0
- data/src/toxi/geom/VecMathUtil.java +100 -0
- data/src/toxi/geom/XAxisCylinder.java +64 -0
- data/src/toxi/geom/YAxisCylinder.java +65 -0
- data/src/toxi/geom/ZAxisCylinder.java +64 -0
- data/src/toxi/geom/mesh/BezierPatch.java +200 -0
- data/src/toxi/geom/mesh/BoxSelector.java +62 -0
- data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
- data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
- data/src/toxi/geom/mesh/Face.java +176 -0
- data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
- data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
- data/src/toxi/geom/mesh/Mesh3D.java +224 -0
- data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
- data/src/toxi/geom/mesh/OBJWriter.java +194 -0
- data/src/toxi/geom/mesh/PLYWriter.java +167 -0
- data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
- data/src/toxi/geom/mesh/STLColorModel.java +54 -0
- data/src/toxi/geom/mesh/STLReader.java +185 -0
- data/src/toxi/geom/mesh/STLWriter.java +323 -0
- data/src/toxi/geom/mesh/SphereFunction.java +156 -0
- data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
- data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
- data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
- data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
- data/src/toxi/geom/mesh/Terrain.java +451 -0
- data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
- data/src/toxi/geom/mesh/Vertex.java +78 -0
- data/src/toxi/geom/mesh/VertexSelector.java +193 -0
- data/src/toxi/geom/mesh/WEFace.java +100 -0
- data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
- data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
- data/src/toxi/geom/mesh/WEVertex.java +134 -0
- data/src/toxi/geom/mesh/WingedEdge.java +115 -0
- data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
- data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
- data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
- data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
- data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
- data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
- data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
- data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
- data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
- data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
- data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
- data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
- data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
- data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
- data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
- data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
- data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
- data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
- data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
- data/src/toxi/geom/nurbs/ControlNet.java +148 -0
- data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
- data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
- data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
- data/src/toxi/geom/nurbs/KnotVector.java +333 -0
- data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
- data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
- data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
- data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
- data/src/toxi/image/util/Filter8bit.java +331 -0
- data/src/toxi/image/util/TiledFrameExporter.java +162 -0
- data/src/toxi/math/BezierInterpolation.java +102 -0
- data/src/toxi/math/CircularInterpolation.java +88 -0
- data/src/toxi/math/CosineInterpolation.java +51 -0
- data/src/toxi/math/DecimatedInterpolation.java +77 -0
- data/src/toxi/math/ExponentialInterpolation.java +68 -0
- data/src/toxi/math/InterpolateStrategy.java +60 -0
- data/src/toxi/math/Interpolation2D.java +93 -0
- data/src/toxi/math/LinearInterpolation.java +46 -0
- data/src/toxi/math/MathUtils.java +990 -0
- data/src/toxi/math/NonLinearScaleMap.java +101 -0
- data/src/toxi/math/ScaleMap.java +183 -0
- data/src/toxi/math/SigmoidInterpolation.java +78 -0
- data/src/toxi/math/SinCosLUT.java +141 -0
- data/src/toxi/math/ThresholdInterpolation.java +58 -0
- data/src/toxi/math/ZoomLensInterpolation.java +126 -0
- data/src/toxi/math/conversion/UnitTranslator.java +161 -0
- data/src/toxi/math/noise/PerlinNoise.java +281 -0
- data/src/toxi/math/noise/SimplexNoise.java +542 -0
- data/src/toxi/math/waves/AMFMSineWave.java +143 -0
- data/src/toxi/math/waves/AbstractWave.java +248 -0
- data/src/toxi/math/waves/ConstantWave.java +48 -0
- data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
- data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
- data/src/toxi/math/waves/FMSineWave.java +142 -0
- data/src/toxi/math/waves/FMSquareWave.java +143 -0
- data/src/toxi/math/waves/FMTriangleWave.java +126 -0
- data/src/toxi/math/waves/SineWave.java +81 -0
- data/src/toxi/math/waves/Wave2D.java +68 -0
- data/src/toxi/math/waves/WaveState.java +69 -0
- data/src/toxi/music/scale/AbstractScale.java +117 -0
- data/src/toxi/music/scale/GenericScale.java +66 -0
- data/src/toxi/music/scale/MajorScale.java +41 -0
- data/src/toxi/newmesh/AttributedEdge.java +106 -0
- data/src/toxi/newmesh/AttributedFace.java +63 -0
- data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
- data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
- data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
- data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
- data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
- data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
- data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
- data/src/toxi/newmesh/SpatialIndex.java +78 -0
- data/src/toxi/physics2d/ParticlePath2D.java +100 -0
- data/src/toxi/physics2d/ParticleString2D.java +184 -0
- data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
- data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
- data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
- data/src/toxi/physics2d/VerletParticle2D.java +457 -0
- data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
- data/src/toxi/physics2d/VerletSpring2D.java +181 -0
- data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
- data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
- data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
- data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
- data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
- data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
- data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
- data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
- data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
- data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
- data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
- data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
- data/src/toxi/physics3d/ParticlePath3D.java +100 -0
- data/src/toxi/physics3d/ParticleString3D.java +184 -0
- data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
- data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
- data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
- data/src/toxi/physics3d/VerletParticle3D.java +385 -0
- data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
- data/src/toxi/physics3d/VerletSpring3D.java +180 -0
- data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
- data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
- data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
- data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
- data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
- data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
- data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
- data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
- data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
- data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
- data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
- data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
- data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
- data/src/toxi/processing/ArrowModifier.java +116 -0
- data/src/toxi/processing/DashedLineModifier.java +48 -0
- data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
- data/src/toxi/processing/Line2DRenderModifier.java +18 -0
- data/src/toxi/processing/MeshToVBO.java +94 -0
- data/src/toxi/processing/NormalMapper.java +18 -0
- data/src/toxi/processing/POVInterface.java +121 -0
- data/src/toxi/processing/POVMesh.java +219 -0
- data/src/toxi/processing/POVWriter.java +460 -0
- data/src/toxi/processing/RCOpaque.java +77 -0
- data/src/toxi/processing/RCTransp.java +78 -0
- data/src/toxi/processing/TextureBuilder.java +232 -0
- data/src/toxi/processing/Textures.java +110 -0
- data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
- data/src/toxi/processing/Tracing.java +25 -0
- data/src/toxi/processing/XYZNormalMapper.java +30 -0
- data/src/toxi/sim/automata/CAMatrix.java +297 -0
- data/src/toxi/sim/automata/CARule.java +76 -0
- data/src/toxi/sim/automata/CARule2D.java +354 -0
- data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
- data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
- data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
- data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
- data/src/toxi/sim/dla/DLA.java +497 -0
- data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
- data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
- data/src/toxi/sim/dla/DLAEventListener.java +57 -0
- data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
- data/src/toxi/sim/dla/DLAParticle.java +102 -0
- data/src/toxi/sim/dla/DLASegment.java +88 -0
- data/src/toxi/sim/dla/PipelineOrder.java +50 -0
- data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
- data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
- data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
- data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
- data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
- data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
- data/src/toxi/sim/grayscott/GrayScott.java +469 -0
- data/src/toxi/util/DateUtils.java +141 -0
- data/src/toxi/util/FileSequenceDescriptor.java +181 -0
- data/src/toxi/util/FileUtils.java +467 -0
- data/src/toxi/util/datatypes/ArraySet.java +128 -0
- data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
- data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
- data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
- data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
- data/src/toxi/util/datatypes/DoubleRange.java +251 -0
- data/src/toxi/util/datatypes/FloatRange.java +251 -0
- data/src/toxi/util/datatypes/GenericSet.java +215 -0
- data/src/toxi/util/datatypes/IntegerRange.java +247 -0
- data/src/toxi/util/datatypes/IntegerSet.java +149 -0
- data/src/toxi/util/datatypes/ItemIndex.java +72 -0
- data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
- data/src/toxi/util/datatypes/TypedProperties.java +291 -0
- data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
- data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
- data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
- data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
- data/src/toxi/util/events/EventDispatcher.java +86 -0
- data/src/toxi/volume/AdditiveBrush.java +19 -0
- data/src/toxi/volume/ArrayIsoSurface.java +297 -0
- data/src/toxi/volume/BoxBrush.java +100 -0
- data/src/toxi/volume/BrushMode.java +16 -0
- data/src/toxi/volume/HashIsoSurface.java +354 -0
- data/src/toxi/volume/IsoSurface.java +59 -0
- data/src/toxi/volume/MarchingCubesIndex.java +312 -0
- data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
- data/src/toxi/volume/MeshVoxelizer.java +216 -0
- data/src/toxi/volume/MultiplyBrush.java +20 -0
- data/src/toxi/volume/PeakBrush.java +21 -0
- data/src/toxi/volume/ReplaceBrush.java +19 -0
- data/src/toxi/volume/RoundBrush.java +113 -0
- data/src/toxi/volume/VolumetricBrush.java +160 -0
- data/src/toxi/volume/VolumetricHashMap.java +179 -0
- data/src/toxi/volume/VolumetricSpace.java +195 -0
- data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
- data/toxiclibs.gemspec +34 -0
- metadata +424 -27
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jgeom: Geometry Library fo Java
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2005 Samuel Gerber
|
|
5
|
+
*
|
|
6
|
+
* This program is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU General Public License
|
|
8
|
+
* as published by the Free Software Foundation; either version 2
|
|
9
|
+
* of the License, or (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
19
|
+
*/
|
|
20
|
+
package toxi.geom.nurbs;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* An InterpolationException is thrown if Nurbs could not be interpolated from
|
|
24
|
+
* the given points.
|
|
25
|
+
*
|
|
26
|
+
* @author sg
|
|
27
|
+
* @version 1.0
|
|
28
|
+
*/
|
|
29
|
+
public class InterpolationException extends Exception {
|
|
30
|
+
|
|
31
|
+
private static final long serialVersionUID = 1L;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
public InterpolationException() {
|
|
37
|
+
super();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param arg0
|
|
43
|
+
*/
|
|
44
|
+
public InterpolationException(String arg0) {
|
|
45
|
+
super(arg0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param arg0
|
|
51
|
+
* @param arg1
|
|
52
|
+
*/
|
|
53
|
+
public InterpolationException(String arg0, Throwable arg1) {
|
|
54
|
+
super(arg0, arg1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param arg0
|
|
60
|
+
*/
|
|
61
|
+
public InterpolationException(Throwable arg0) {
|
|
62
|
+
super(arg0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jgeom: Geometry Library fo Java
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2005 Samuel Gerber
|
|
5
|
+
*
|
|
6
|
+
* This program is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU General Public License
|
|
8
|
+
* as published by the Free Software Foundation; either version 2
|
|
9
|
+
* of the License, or (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
19
|
+
*/
|
|
20
|
+
package toxi.geom.nurbs;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* KnotVector, assembles the knots values of a NURBS and its degree.
|
|
24
|
+
*
|
|
25
|
+
* @author sg
|
|
26
|
+
* @version 1.0
|
|
27
|
+
*/
|
|
28
|
+
public class KnotVector {
|
|
29
|
+
|
|
30
|
+
private boolean isOpen;
|
|
31
|
+
private final float knots[];
|
|
32
|
+
private final int degree;
|
|
33
|
+
private final int n;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a Knotvector from the given knot values of the desired degree.
|
|
37
|
+
*
|
|
38
|
+
* @param knots
|
|
39
|
+
* knot values
|
|
40
|
+
* @param degree
|
|
41
|
+
* degree of Nurbs
|
|
42
|
+
*/
|
|
43
|
+
public KnotVector(float knots[], int degree)
|
|
44
|
+
throws IllegalArgumentException {
|
|
45
|
+
this.knots = knots;
|
|
46
|
+
this.degree = degree;
|
|
47
|
+
n = knots.length - degree - 2;
|
|
48
|
+
for (int i = 1; i < knots.length; i++) {
|
|
49
|
+
if (knots[i - 1] > knots[i]) {
|
|
50
|
+
throw new IllegalArgumentException("Knots not valid knot["
|
|
51
|
+
+ (i - 1) + "] > knot[" + i + "]: knot[" + (i - 1)
|
|
52
|
+
+ "]=" + knots[i - 1] + " > knot[" + i + "]="
|
|
53
|
+
+ knots[i]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
int m = knots.length - 1;
|
|
58
|
+
|
|
59
|
+
// Check if it is an open knot vector
|
|
60
|
+
isOpen = true;
|
|
61
|
+
for (int k = 0; k < degree && isOpen; k++) {
|
|
62
|
+
if (knots[k] != knots[k + 1]) {
|
|
63
|
+
isOpen = false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (int k = m; k > m - degree && isOpen; k--) {
|
|
67
|
+
if (knots[k] != knots[k - 1]) {
|
|
68
|
+
isOpen = false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Gets the basis function values for the given u value. This function
|
|
76
|
+
* calculates firstly the span which is needed in order to calculate the
|
|
77
|
+
* basis functions values.
|
|
78
|
+
*
|
|
79
|
+
* @param u
|
|
80
|
+
* Value to calculate basis functions for.
|
|
81
|
+
* @return basis function values
|
|
82
|
+
*/
|
|
83
|
+
public double[] basisFunctions(float u) {
|
|
84
|
+
return basisFunctions(findSpan(u), u);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Calculates the basis function values for the given u value, when it's
|
|
89
|
+
* already known in which span u lies.
|
|
90
|
+
*
|
|
91
|
+
* @param span
|
|
92
|
+
* The span u lies in
|
|
93
|
+
* @param u
|
|
94
|
+
* Value to calculate basis functions for.
|
|
95
|
+
* @return basis function values
|
|
96
|
+
*/
|
|
97
|
+
public double[] basisFunctions(int span, float u) {
|
|
98
|
+
final int d1 = degree + 1;
|
|
99
|
+
double res[] = new double[d1];
|
|
100
|
+
double left[] = new double[d1];
|
|
101
|
+
double right[] = new double[d1];
|
|
102
|
+
res[0] = 1;
|
|
103
|
+
for (int j = 1; j < d1; j++) {
|
|
104
|
+
left[j] = u - knots[span + 1 - j];
|
|
105
|
+
right[j] = knots[span + j] - u;
|
|
106
|
+
double saved = 0;
|
|
107
|
+
for (int r = 0; r < j; r++) {
|
|
108
|
+
double tmp = res[r] / (right[r + 1] + left[j - r]);
|
|
109
|
+
res[r] = saved + right[r + 1] * tmp;
|
|
110
|
+
saved = left[j - r] * tmp;
|
|
111
|
+
}
|
|
112
|
+
res[j] = saved;
|
|
113
|
+
}
|
|
114
|
+
return res;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Calculates the basis functions and its derivatives up to the given grade.
|
|
119
|
+
*
|
|
120
|
+
* @param u
|
|
121
|
+
* Value to calculate basis functions and derivatives for.
|
|
122
|
+
* @param grade
|
|
123
|
+
* grade to calculate derivations for.
|
|
124
|
+
* @return an array of basis function values or derivated basis functions
|
|
125
|
+
* values. The first array is the degree of dderivation in the
|
|
126
|
+
* second array rhe values are stored. <br>
|
|
127
|
+
* Example: <br>
|
|
128
|
+
* <code>
|
|
129
|
+
* float[]][] f=dersBasisFuns(0.1f, 3);
|
|
130
|
+
* float value=f[0][1]; //In value is know the second value of the basis function derived 0 times stored.
|
|
131
|
+
* </code>
|
|
132
|
+
*
|
|
133
|
+
*/
|
|
134
|
+
public float[][] derivBasisFunctions(float u, int grade) {
|
|
135
|
+
int span = findSpan(u);
|
|
136
|
+
return derivBasisFunctions(span, u, grade);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Calculates the basis functions and its derivatives up to the given grade.
|
|
141
|
+
*
|
|
142
|
+
* @param span
|
|
143
|
+
* Span the given value lies in.
|
|
144
|
+
* @param u
|
|
145
|
+
* Value to calculate basis functions and derivatives for.
|
|
146
|
+
* @param grade
|
|
147
|
+
* grade to calculate derivations for.
|
|
148
|
+
* @return an array of basis function values or derivated basis functions
|
|
149
|
+
* values
|
|
150
|
+
* @see KnotVector#derivBasisFunctions(float, int)
|
|
151
|
+
*/
|
|
152
|
+
public float[][] derivBasisFunctions(int span, float u, int grade) {
|
|
153
|
+
float[][] ders = new float[grade + 1][degree + 1];
|
|
154
|
+
float[][] ndu = new float[degree + 1][degree + 1];
|
|
155
|
+
ndu[0][0] = 1.0f;
|
|
156
|
+
float[] left = new float[degree + 1];
|
|
157
|
+
float[] right = new float[degree + 1];
|
|
158
|
+
int j1, j2;
|
|
159
|
+
for (int j = 1; j <= degree; j++) {
|
|
160
|
+
left[j] = u - knots[span + 1 - j];
|
|
161
|
+
right[j] = knots[span + j] - u;
|
|
162
|
+
float saved = 0.0f;
|
|
163
|
+
for (int r = 0; r < j; r++) {
|
|
164
|
+
ndu[j][r] = right[r + 1] + left[j - r];
|
|
165
|
+
float temp = ndu[r][j - 1] / ndu[j][r];
|
|
166
|
+
ndu[r][j] = saved + right[r + 1] * temp;
|
|
167
|
+
saved = left[j - r] * temp;
|
|
168
|
+
}
|
|
169
|
+
ndu[j][j] = saved;
|
|
170
|
+
}
|
|
171
|
+
for (int j = 0; j <= degree; j++) {
|
|
172
|
+
ders[0][j] = ndu[j][degree];
|
|
173
|
+
}
|
|
174
|
+
for (int r = 0; r <= degree; r++) {
|
|
175
|
+
int s1 = 0;
|
|
176
|
+
int s2 = 1;
|
|
177
|
+
float[][] a = new float[2][degree + 1];
|
|
178
|
+
a[0][0] = 1.0f;
|
|
179
|
+
for (int k = 1; k <= grade; k++) {
|
|
180
|
+
float d = 0.0f;
|
|
181
|
+
final int rk = r - k;
|
|
182
|
+
final int pk = degree - k;
|
|
183
|
+
final float[] as1 = a[s1];
|
|
184
|
+
final float[] as2 = a[s2];
|
|
185
|
+
if (r >= k) {
|
|
186
|
+
as2[0] = d = as1[0] / ndu[pk + 1][rk];
|
|
187
|
+
d *= ndu[rk][pk];
|
|
188
|
+
}
|
|
189
|
+
if (rk >= -1) {
|
|
190
|
+
j1 = 1;
|
|
191
|
+
} else {
|
|
192
|
+
j1 = -rk;
|
|
193
|
+
}
|
|
194
|
+
if (r - 1 <= pk) {
|
|
195
|
+
j2 = k - 1;
|
|
196
|
+
} else {
|
|
197
|
+
j2 = degree - r;
|
|
198
|
+
}
|
|
199
|
+
for (int j = j1; j <= j2; j++) {
|
|
200
|
+
as2[j] = (as1[j] - as1[j - 1]) / ndu[pk + 1][rk + j];
|
|
201
|
+
d += as2[j] * ndu[rk + j][pk];
|
|
202
|
+
}
|
|
203
|
+
if (r <= pk) {
|
|
204
|
+
as2[k] = -as1[k - 1] / ndu[pk + 1][r];
|
|
205
|
+
d += as2[k] * ndu[r][pk];
|
|
206
|
+
}
|
|
207
|
+
ders[k][r] = d;
|
|
208
|
+
int j = s1;
|
|
209
|
+
s1 = s2;
|
|
210
|
+
s2 = j;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
int r = degree;
|
|
214
|
+
for (int k = 1; k <= grade; k++) {
|
|
215
|
+
for (int j = 0; j <= degree; j++) {
|
|
216
|
+
ders[k][j] *= r;
|
|
217
|
+
}
|
|
218
|
+
r *= (degree - k);
|
|
219
|
+
}
|
|
220
|
+
return ders;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Finds the span (Position of corresponding knot values in knot vector) a
|
|
225
|
+
* given value belongs to.
|
|
226
|
+
*
|
|
227
|
+
* @param u
|
|
228
|
+
* value to find span for
|
|
229
|
+
* @return Position of span.
|
|
230
|
+
*/
|
|
231
|
+
public int findSpan(float u) {
|
|
232
|
+
if (u >= knots[n + 1]) {
|
|
233
|
+
return n;
|
|
234
|
+
}
|
|
235
|
+
int low = degree;
|
|
236
|
+
int high = n + 1;
|
|
237
|
+
int mid = (low + high) / 2;
|
|
238
|
+
while ((u < knots[mid] || u >= knots[mid + 1]) && low < high) {
|
|
239
|
+
if (u < knots[mid]) {
|
|
240
|
+
high = mid;
|
|
241
|
+
} else {
|
|
242
|
+
low = mid;
|
|
243
|
+
}
|
|
244
|
+
mid = (low + high) / 2;
|
|
245
|
+
}
|
|
246
|
+
return mid;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get the knot value at a specific index.
|
|
251
|
+
*
|
|
252
|
+
* @param i
|
|
253
|
+
* Index to get knot value for
|
|
254
|
+
* @return the knot value
|
|
255
|
+
*/
|
|
256
|
+
public float get(int i) {
|
|
257
|
+
return knots[i];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* get the knot values as float array
|
|
262
|
+
*
|
|
263
|
+
* @return the knot values
|
|
264
|
+
*/
|
|
265
|
+
public float[] getArray() {
|
|
266
|
+
return knots;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Get the degree of the KnotVector
|
|
271
|
+
*
|
|
272
|
+
* @return Degree of the Knotvector
|
|
273
|
+
*/
|
|
274
|
+
public int getDegree() {
|
|
275
|
+
return degree;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Return the nu
|
|
280
|
+
*
|
|
281
|
+
* @return Length of the KnotVector
|
|
282
|
+
*/
|
|
283
|
+
public int getN() {
|
|
284
|
+
return n;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
*
|
|
289
|
+
* @return
|
|
290
|
+
*/
|
|
291
|
+
public int getNumberOfSegments() {
|
|
292
|
+
int seg = 0;
|
|
293
|
+
float u = knots[0];
|
|
294
|
+
for (int i = 1; i < knots.length; i++) {
|
|
295
|
+
if (u != knots[i]) {
|
|
296
|
+
seg++;
|
|
297
|
+
u = knots[i];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return seg;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
*
|
|
305
|
+
* @return
|
|
306
|
+
*/
|
|
307
|
+
public synchronized boolean isOpen() {
|
|
308
|
+
return isOpen;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
*
|
|
313
|
+
* @return
|
|
314
|
+
*/
|
|
315
|
+
public int length() {
|
|
316
|
+
return knots.length;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Set the knot value at a specific index. After this operation a call to
|
|
321
|
+
* isValid may be needed if one is not sure if the KnotVector with the
|
|
322
|
+
* changed value is valid for a Nurbs.
|
|
323
|
+
*
|
|
324
|
+
* @param i
|
|
325
|
+
* Index to set knot value
|
|
326
|
+
* @param val
|
|
327
|
+
* value to set the knot too
|
|
328
|
+
*/
|
|
329
|
+
public void set(int i, float val) {
|
|
330
|
+
knots[i] = val;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
}
|
|
@@ -0,0 +1,815 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jgeom: Geometry Library fo Java
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2005 Samuel Gerber
|
|
5
|
+
*
|
|
6
|
+
* This program is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU General Public License
|
|
8
|
+
* as published by the Free Software Foundation; either version 2
|
|
9
|
+
* of the License, or (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
* GNU General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU General Public License
|
|
17
|
+
* along with this program; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
19
|
+
*/
|
|
20
|
+
package toxi.geom.nurbs;
|
|
21
|
+
|
|
22
|
+
import toxi.geom.Axis3D;
|
|
23
|
+
import toxi.geom.GMatrix;
|
|
24
|
+
import toxi.geom.GVector;
|
|
25
|
+
import toxi.geom.Origin3D;
|
|
26
|
+
import toxi.geom.ReadonlyVec3D;
|
|
27
|
+
import toxi.geom.SingularMatrixException;
|
|
28
|
+
import toxi.geom.Vec3D;
|
|
29
|
+
import toxi.geom.Vec4D;
|
|
30
|
+
import toxi.math.MathUtils;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* This class offers some static methods to create NurbsSurfaces and NurbsCurves
|
|
34
|
+
* from diffrent inputs.
|
|
35
|
+
*
|
|
36
|
+
* @author sg
|
|
37
|
+
* @version 1.0
|
|
38
|
+
*/
|
|
39
|
+
public final class NurbsCreator {
|
|
40
|
+
|
|
41
|
+
private static KnotVector averaging(final float[] uk, final int p) {
|
|
42
|
+
int m = uk.length + p;
|
|
43
|
+
int n = uk.length - 1;
|
|
44
|
+
float ip = 1f / p;
|
|
45
|
+
float[] u = new float[m + 1];
|
|
46
|
+
for (int i = 0; i <= p; i++) {
|
|
47
|
+
u[m - i] = 1;
|
|
48
|
+
}
|
|
49
|
+
for (int j = 1; j <= n - p; j++) {
|
|
50
|
+
float sum = 0;
|
|
51
|
+
for (int i = j; i <= j + p - 1; i++) {
|
|
52
|
+
sum += uk[i];
|
|
53
|
+
}
|
|
54
|
+
u[j + p] = sum * ip;
|
|
55
|
+
}
|
|
56
|
+
return new KnotVector(u, p);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private static float[] centripetal(Vec3D[] points) {
|
|
60
|
+
int n = points.length - 1;
|
|
61
|
+
float d = 0;
|
|
62
|
+
float[] uk = new float[n + 1];
|
|
63
|
+
uk[n] = 1;
|
|
64
|
+
double[] tmp = new double[n];
|
|
65
|
+
for (int k = 1; k <= n; k++) {
|
|
66
|
+
tmp[k - 1] = Math.sqrt(points[k].distanceTo(points[k - 1]));
|
|
67
|
+
d += tmp[k - 1];
|
|
68
|
+
}
|
|
69
|
+
d = 1f / d;
|
|
70
|
+
for (int i = 1; i < n; i++) {
|
|
71
|
+
uk[i] = uk[i - 1] + (float) (tmp[i - 1] * d);
|
|
72
|
+
}
|
|
73
|
+
return uk;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create an Arc.
|
|
78
|
+
*
|
|
79
|
+
* @param o
|
|
80
|
+
* Origin to creat arc around
|
|
81
|
+
* @param r
|
|
82
|
+
* Radius of the arc.
|
|
83
|
+
* @param thetaStart
|
|
84
|
+
* Start angle of the arc in radians
|
|
85
|
+
* @param thetaEnd
|
|
86
|
+
* End angle of the arc in radians. If end angle is smaller than
|
|
87
|
+
* start angle, the end angle is increased by 2*PI.
|
|
88
|
+
* @return A NurbsCurve for the Arc.
|
|
89
|
+
*/
|
|
90
|
+
public static NurbsCurve createArc(Origin3D o, float r, float thetaStart,
|
|
91
|
+
float thetaEnd) {
|
|
92
|
+
Vec3D tmp = new Vec3D();
|
|
93
|
+
|
|
94
|
+
if (thetaEnd < thetaStart) {
|
|
95
|
+
thetaEnd += MathUtils.TWO_PI;
|
|
96
|
+
}
|
|
97
|
+
double theta = thetaEnd - thetaStart;
|
|
98
|
+
|
|
99
|
+
int narcs = 4;
|
|
100
|
+
if (theta <= MathUtils.HALF_PI) {
|
|
101
|
+
narcs = 1;
|
|
102
|
+
} else if (theta <= MathUtils.PI) {
|
|
103
|
+
narcs = 2;
|
|
104
|
+
} else if (theta <= MathUtils.THREE_HALVES_PI) {
|
|
105
|
+
narcs = 3;
|
|
106
|
+
}
|
|
107
|
+
double dtheta = theta / narcs;
|
|
108
|
+
int n = 2 * narcs;
|
|
109
|
+
double w1 = Math.cos(dtheta / 2);
|
|
110
|
+
|
|
111
|
+
final float sinStart = (float) Math.sin(thetaStart);
|
|
112
|
+
final float cosStart = (float) Math.cos(thetaStart);
|
|
113
|
+
tmp.set(o.xAxis).scaleSelf(r * cosStart);
|
|
114
|
+
Vec3D p0 = new Vec3D(o.origin).addSelf(tmp);
|
|
115
|
+
tmp.set(o.yAxis).scaleSelf(r * sinStart);
|
|
116
|
+
p0.addSelf(tmp);
|
|
117
|
+
|
|
118
|
+
tmp.set(o.yAxis).scaleSelf(cosStart);
|
|
119
|
+
Vec3D t0 = new Vec3D(o.xAxis).scaleSelf(-sinStart).addSelf(tmp);
|
|
120
|
+
|
|
121
|
+
Vec4D[] cps = new Vec4D[n + 1];
|
|
122
|
+
cps[0] = new Vec4D(p0, 1);
|
|
123
|
+
int index = 0;
|
|
124
|
+
double angle = thetaStart;
|
|
125
|
+
|
|
126
|
+
Vec3D p1 = new Vec3D();
|
|
127
|
+
Vec3D p2 = new Vec3D();
|
|
128
|
+
Vec3D t2 = new Vec3D();
|
|
129
|
+
for (int i = 1; i <= narcs; i++) {
|
|
130
|
+
angle += dtheta;
|
|
131
|
+
final double sin = Math.sin(angle);
|
|
132
|
+
final double cos = Math.cos(angle);
|
|
133
|
+
|
|
134
|
+
tmp.set(o.xAxis).scaleSelf((float) (r * cos));
|
|
135
|
+
p2.set(o.origin).addSelf(tmp);
|
|
136
|
+
tmp.set(o.yAxis).scaleSelf((float) (r * sin));
|
|
137
|
+
p2.addSelf(tmp);
|
|
138
|
+
|
|
139
|
+
cps[index + 2] = new Vec4D(p2, 1);
|
|
140
|
+
|
|
141
|
+
t2.set(o.xAxis).scaleSelf((float) -sin);
|
|
142
|
+
tmp.set(o.yAxis).scaleSelf((float) cos);
|
|
143
|
+
t2.addSelf(tmp);
|
|
144
|
+
|
|
145
|
+
lineIntersect3D(p0, t0, p2, t2, p1, p1);
|
|
146
|
+
|
|
147
|
+
cps[index + 1] = new Vec4D(p1, (float) w1);
|
|
148
|
+
index += 2;
|
|
149
|
+
if (i < narcs) {
|
|
150
|
+
p0.set(p2);
|
|
151
|
+
t0.set(t2);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
int j = n + 1;
|
|
155
|
+
float[] uKnot = new float[j + 3];
|
|
156
|
+
for (int i = 0; i < 3; i++) {
|
|
157
|
+
uKnot[i + j] = 1;
|
|
158
|
+
}
|
|
159
|
+
switch (narcs) {
|
|
160
|
+
case 2:
|
|
161
|
+
uKnot[3] = 0.5f;
|
|
162
|
+
uKnot[4] = 0.5f;
|
|
163
|
+
break;
|
|
164
|
+
case 3:
|
|
165
|
+
uKnot[3] = uKnot[4] = MathUtils.THIRD;
|
|
166
|
+
uKnot[5] = uKnot[6] = 2 * MathUtils.THIRD;
|
|
167
|
+
break;
|
|
168
|
+
case 4:
|
|
169
|
+
uKnot[3] = 0.25f;
|
|
170
|
+
uKnot[4] = 0.25f;
|
|
171
|
+
uKnot[5] = 0.5f;
|
|
172
|
+
uKnot[6] = 0.5f;
|
|
173
|
+
uKnot[7] = 0.75f;
|
|
174
|
+
uKnot[8] = 0.75f;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return new BasicNurbsCurve(cps, uKnot, 2);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Create a full-circle NurbsCurve around the given Origin with radius r.
|
|
183
|
+
* The NurbsCurve has controlpolygon which has 7 controlpoints and the shape
|
|
184
|
+
* of quadrat.
|
|
185
|
+
*
|
|
186
|
+
* @param o
|
|
187
|
+
* Origin to create the full-circle around
|
|
188
|
+
* @param r
|
|
189
|
+
* Radius of the full-circle
|
|
190
|
+
* @return A NurbsCurve for a full-circle
|
|
191
|
+
*/
|
|
192
|
+
public static NurbsCurve createFullCircleQuad7(Origin3D o, float r) {
|
|
193
|
+
|
|
194
|
+
Vec4D[] cp = new Vec4D[7];
|
|
195
|
+
cp[0] = new Vec4D(o.xAxis.scale(r), 1);
|
|
196
|
+
cp[3] = cp[0].getInvertedXYZ();
|
|
197
|
+
cp[6] = cp[0].copy();
|
|
198
|
+
|
|
199
|
+
cp[1] = new Vec4D(o.yAxis.add(o.xAxis).scaleSelf(r), 0.5f);
|
|
200
|
+
cp[4] = cp[1].getInvertedXYZ();
|
|
201
|
+
|
|
202
|
+
cp[2] = new Vec4D(o.xAxis.getInverted().addSelf(o.yAxis).scaleSelf(r),
|
|
203
|
+
0.5f);
|
|
204
|
+
cp[5] = cp[2].getInvertedXYZ();
|
|
205
|
+
|
|
206
|
+
for (int i = 0; i < 7; i++) {
|
|
207
|
+
cp[i].addXYZSelf(o.origin);
|
|
208
|
+
}
|
|
209
|
+
float[] u = {
|
|
210
|
+
0, 0, 0, 0.25f, 0.5f, 0.5f, 0.75f, 1, 1, 1
|
|
211
|
+
};
|
|
212
|
+
return new BasicNurbsCurve(cp, u, 2);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Create a full-circle NurbsCurve around the given Origin with radius r.
|
|
217
|
+
* The NurbsCurve has controlpolygon which has 9 controlpoints and the shape
|
|
218
|
+
* of quadrat.
|
|
219
|
+
*
|
|
220
|
+
* @param o
|
|
221
|
+
* Origin to create the full-circle around
|
|
222
|
+
* @param r
|
|
223
|
+
* Radius of the full-circle
|
|
224
|
+
* @return A NurbsCurve for a full-circle
|
|
225
|
+
*/
|
|
226
|
+
public static NurbsCurve createFullCircleQuad9(Origin3D o, float r) {
|
|
227
|
+
final float w = MathUtils.SQRT2 / 2;
|
|
228
|
+
|
|
229
|
+
Vec4D[] cp = new Vec4D[9];
|
|
230
|
+
cp[0] = new Vec4D(o.xAxis.scale(r), 1);
|
|
231
|
+
cp[4] = cp[0].getInvertedXYZ();
|
|
232
|
+
cp[8] = cp[0].copy();
|
|
233
|
+
|
|
234
|
+
cp[1] = new Vec4D(o.xAxis.add(o.yAxis).scaleSelf(r), w);
|
|
235
|
+
cp[5] = cp[1].getInvertedXYZ();
|
|
236
|
+
|
|
237
|
+
cp[2] = new Vec4D(o.yAxis.scale(r), 1);
|
|
238
|
+
cp[6] = cp[2].getInvertedXYZ();
|
|
239
|
+
|
|
240
|
+
cp[3] = new Vec4D(o.xAxis.getInverted().addSelf(o.yAxis).scaleSelf(r),
|
|
241
|
+
w);
|
|
242
|
+
cp[7] = cp[3].getInvertedXYZ();
|
|
243
|
+
|
|
244
|
+
for (int i = 0; i < 9; i++) {
|
|
245
|
+
cp[i].addXYZSelf(o.origin);
|
|
246
|
+
}
|
|
247
|
+
float[] u = {
|
|
248
|
+
0, 0, 0, 0.25f, 0.25f, 0.5f, 0.5f, 0.75f, 0.75f, 1, 1, 1
|
|
249
|
+
};
|
|
250
|
+
return new BasicNurbsCurve(cp, u, 2);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Create a revolved NurbsSurface from the given NurbsCurve around the given
|
|
255
|
+
* axis whith the angle theta.
|
|
256
|
+
*
|
|
257
|
+
* @param a
|
|
258
|
+
* Axis to revolve around.
|
|
259
|
+
* @param curve
|
|
260
|
+
* NurbsCurve to revolve
|
|
261
|
+
* @param theta
|
|
262
|
+
* Angle to revolve
|
|
263
|
+
* @return The revolved NurbsSurface
|
|
264
|
+
*/
|
|
265
|
+
// TODO:call createRevolvedSurface(Axis3D a, NurbsCurve curve, double
|
|
266
|
+
// thetaStart, double thetaEnd) as as it is tested
|
|
267
|
+
public static NurbsSurface createRevolvedSurface(Axis3D a,
|
|
268
|
+
NurbsCurve curve, double theta) {
|
|
269
|
+
int narcs = 4;
|
|
270
|
+
if (theta <= MathUtils.HALF_PI) {
|
|
271
|
+
narcs = 1;
|
|
272
|
+
} else if (theta <= MathUtils.PI) {
|
|
273
|
+
narcs = 2;
|
|
274
|
+
} else if (theta <= MathUtils.THREE_HALVES_PI) {
|
|
275
|
+
narcs = 3;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
int j = 3 + 2 * (narcs - 1);
|
|
279
|
+
final double dtheta = theta / narcs;
|
|
280
|
+
final float[] uKnot = new float[j + 3];
|
|
281
|
+
for (int i = 0; i < 3; i++) {
|
|
282
|
+
uKnot[j + i] = 1;
|
|
283
|
+
}
|
|
284
|
+
switch (narcs) {
|
|
285
|
+
case 2:
|
|
286
|
+
uKnot[3] = 0.5f;
|
|
287
|
+
uKnot[4] = 0.5f;
|
|
288
|
+
break;
|
|
289
|
+
case 3:
|
|
290
|
+
uKnot[3] = uKnot[4] = MathUtils.THIRD;
|
|
291
|
+
uKnot[5] = uKnot[6] = 2 * MathUtils.THIRD;
|
|
292
|
+
break;
|
|
293
|
+
case 4:
|
|
294
|
+
uKnot[3] = 0.25f;
|
|
295
|
+
uKnot[4] = 0.25f;
|
|
296
|
+
uKnot[5] = 0.5f;
|
|
297
|
+
uKnot[6] = 0.5f;
|
|
298
|
+
uKnot[7] = 0.75f;
|
|
299
|
+
uKnot[8] = 0.75f;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
double angle = 0;
|
|
304
|
+
final double[] cos = new double[narcs + 1];
|
|
305
|
+
final double[] sin = new double[narcs + 1];
|
|
306
|
+
for (int i = 0; i <= narcs; i++) {
|
|
307
|
+
cos[i] = Math.cos(angle);
|
|
308
|
+
sin[i] = Math.sin(angle);
|
|
309
|
+
angle += dtheta;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
Vec4D[] pj = curve.getControlPoints();
|
|
313
|
+
Vec3D P0 = new Vec3D();
|
|
314
|
+
final Vec3D P2 = new Vec3D();
|
|
315
|
+
final Vec3D O = new Vec3D();
|
|
316
|
+
final Vec3D T2 = new Vec3D();
|
|
317
|
+
final Vec3D T0 = new Vec3D();
|
|
318
|
+
final Vec3D tmp = new Vec3D();
|
|
319
|
+
final Vec3D X = new Vec3D();
|
|
320
|
+
final Vec3D Y = new Vec3D();
|
|
321
|
+
final Vec4D[][] pij = new Vec4D[2 * narcs + 1][pj.length];
|
|
322
|
+
final double wm = Math.cos(dtheta / 2);
|
|
323
|
+
for (j = 0; j < pj.length; j++) {
|
|
324
|
+
pointToLine3D(a.origin, a.dir, pj[j].to3D(), O);
|
|
325
|
+
X.set(pj[j].to3D().subSelf(O));
|
|
326
|
+
final double r = X.magnitude();
|
|
327
|
+
if (r == 0) {
|
|
328
|
+
X.set(O);
|
|
329
|
+
}
|
|
330
|
+
X.normalize();
|
|
331
|
+
a.dir.crossInto(X, Y);
|
|
332
|
+
pij[0][j] = new Vec4D(pj[j]);
|
|
333
|
+
P0 = pj[j].to3D();
|
|
334
|
+
T0.set(Y);
|
|
335
|
+
int index = 0;
|
|
336
|
+
for (int i = 1; i <= narcs; i++) {
|
|
337
|
+
tmp.set(X).scaleSelf((float) (r * cos[i]));
|
|
338
|
+
P2.set(O).addSelf(tmp);
|
|
339
|
+
tmp.set(Y).scaleSelf((float) (r * sin[i]));
|
|
340
|
+
P2.addSelf(tmp);
|
|
341
|
+
|
|
342
|
+
pij[index + 2][j] = new Vec4D(P2, pj[j].w);
|
|
343
|
+
|
|
344
|
+
tmp.set(Y).scaleSelf((float) cos[i]);
|
|
345
|
+
T2.set(X).scaleSelf((float) -sin[i]).addSelf(tmp);
|
|
346
|
+
|
|
347
|
+
lineIntersect3D(P0, T0, P2, T2, tmp, tmp);
|
|
348
|
+
pij[index + 1][j] = new Vec4D(tmp, (float) (wm * pj[j].w));
|
|
349
|
+
|
|
350
|
+
index += 2;
|
|
351
|
+
if (i < narcs) {
|
|
352
|
+
P0.set(P2);
|
|
353
|
+
T0.set(T2);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
ControlNet cnet = new ControlNet(pij);
|
|
359
|
+
return new BasicNurbsSurface(cnet, uKnot, curve.getKnots(), 2,
|
|
360
|
+
curve.getDegree());
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Create a revolved NurbsSurface from the given NurbsCurve around the given
|
|
365
|
+
* axis whith the angle theta.
|
|
366
|
+
*
|
|
367
|
+
* @param a
|
|
368
|
+
* Axis to revolve around.
|
|
369
|
+
* @param curve
|
|
370
|
+
* NurbsCurve to revolve
|
|
371
|
+
* @param thetaStart
|
|
372
|
+
* Angle to start revolution
|
|
373
|
+
* @param thetaEnd
|
|
374
|
+
* Angle to end revolution
|
|
375
|
+
* @return The revolved NurbsSurface
|
|
376
|
+
*/
|
|
377
|
+
public static NurbsSurface createRevolvedSurface(Axis3D a,
|
|
378
|
+
NurbsCurve curve, double thetaStart, double thetaEnd) {
|
|
379
|
+
int narcs = 4;
|
|
380
|
+
if (thetaStart > thetaEnd) {
|
|
381
|
+
double tmp = thetaEnd;
|
|
382
|
+
thetaEnd = thetaStart;
|
|
383
|
+
thetaStart = tmp;
|
|
384
|
+
}
|
|
385
|
+
double theta = thetaEnd - thetaStart;
|
|
386
|
+
if (theta <= MathUtils.HALF_PI) {
|
|
387
|
+
narcs = 1;
|
|
388
|
+
} else if (theta <= MathUtils.PI) {
|
|
389
|
+
narcs = 2;
|
|
390
|
+
} else if (theta <= MathUtils.THREE_HALVES_PI) {
|
|
391
|
+
narcs = 3;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
int j = 3 + 2 * (narcs - 1);
|
|
395
|
+
final double dtheta = theta / narcs;
|
|
396
|
+
final float[] uKnot = new float[j + 3];
|
|
397
|
+
for (int i = 0; i < 3; i++) {
|
|
398
|
+
uKnot[i] = 0;
|
|
399
|
+
uKnot[j + i] = 1;
|
|
400
|
+
}
|
|
401
|
+
switch (narcs) {
|
|
402
|
+
case 2:
|
|
403
|
+
uKnot[3] = 0.5f;
|
|
404
|
+
uKnot[4] = 0.5f;
|
|
405
|
+
break;
|
|
406
|
+
case 3:
|
|
407
|
+
uKnot[3] = uKnot[4] = MathUtils.THIRD;
|
|
408
|
+
uKnot[5] = uKnot[6] = 2 * MathUtils.THIRD;
|
|
409
|
+
break;
|
|
410
|
+
case 4:
|
|
411
|
+
uKnot[3] = 0.25f;
|
|
412
|
+
uKnot[4] = 0.25f;
|
|
413
|
+
uKnot[5] = 0.5f;
|
|
414
|
+
uKnot[6] = 0.5f;
|
|
415
|
+
uKnot[7] = 0.75f;
|
|
416
|
+
uKnot[8] = 0.75f;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
double angle = thetaStart;
|
|
421
|
+
final double[] cos = new double[narcs + 1];
|
|
422
|
+
final double[] sin = new double[narcs + 1];
|
|
423
|
+
for (int i = 0; i <= narcs; i++) {
|
|
424
|
+
cos[i] = Math.cos(angle);
|
|
425
|
+
sin[i] = Math.sin(angle);
|
|
426
|
+
angle += dtheta;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
final Vec4D[] pj = curve.getControlPoints();
|
|
430
|
+
Vec3D P0 = new Vec3D();
|
|
431
|
+
final Vec3D O = new Vec3D();
|
|
432
|
+
final Vec3D P2 = new Vec3D();
|
|
433
|
+
final Vec3D T2 = new Vec3D();
|
|
434
|
+
final Vec3D T0 = new Vec3D();
|
|
435
|
+
final Vec3D tmp = new Vec3D();
|
|
436
|
+
final Vec3D X = new Vec3D();
|
|
437
|
+
final Vec3D Y = new Vec3D();
|
|
438
|
+
final Vec4D[][] pij = new Vec4D[2 * narcs + 1][pj.length];
|
|
439
|
+
final double wm = Math.cos(dtheta / 2);
|
|
440
|
+
for (j = 0; j < pj.length; j++) {
|
|
441
|
+
pointToLine3D(a.origin, a.dir, pj[j].to3D(), O);
|
|
442
|
+
X.set(pj[j].to3D().subSelf(O));
|
|
443
|
+
final double r = X.magnitude();
|
|
444
|
+
if (r == 0) {
|
|
445
|
+
X.set(O);
|
|
446
|
+
}
|
|
447
|
+
X.normalize();
|
|
448
|
+
a.dir.crossInto(X, Y);
|
|
449
|
+
pij[0][j] = new Vec4D(pj[j]);
|
|
450
|
+
P0 = pj[j].to3D();
|
|
451
|
+
T0.set(Y);
|
|
452
|
+
int index = 0;
|
|
453
|
+
for (int i = 1; i <= narcs; i++) {
|
|
454
|
+
tmp.set(X).scaleSelf((float) (r * cos[i]));
|
|
455
|
+
P2.set(O).addSelf(tmp);
|
|
456
|
+
tmp.set(Y).scaleSelf((float) (r * sin[i]));
|
|
457
|
+
P2.addSelf(tmp);
|
|
458
|
+
|
|
459
|
+
pij[index + 2][j] = new Vec4D(P2, pj[j].w);
|
|
460
|
+
|
|
461
|
+
tmp.set(Y).scaleSelf((float) cos[i]);
|
|
462
|
+
T2.set(X).scaleSelf((float) -sin[i]).addSelf(tmp);
|
|
463
|
+
|
|
464
|
+
lineIntersect3D(P0, T0, P2, T2, tmp, tmp);
|
|
465
|
+
pij[index + 1][j] = new Vec4D(tmp, (float) (wm * pj[j].w));
|
|
466
|
+
|
|
467
|
+
index += 2;
|
|
468
|
+
if (i < narcs) {
|
|
469
|
+
P0.set(P2);
|
|
470
|
+
T0.set(T2);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
ControlNet cnet = new ControlNet(pij);
|
|
475
|
+
return new BasicNurbsSurface(cnet, uKnot, curve.getKnots(), 2,
|
|
476
|
+
curve.getDegree());
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Create a semi-circle NurbsCurve around the given Origin with radius r.
|
|
481
|
+
*
|
|
482
|
+
* @param o
|
|
483
|
+
* Origin to create semi-circle around.
|
|
484
|
+
* @param r
|
|
485
|
+
* Radius of the semi-circle
|
|
486
|
+
* @return A NurbsCurve for a semi-circle
|
|
487
|
+
*/
|
|
488
|
+
public static NurbsCurve createSemiCircle(Origin3D o, float r) {
|
|
489
|
+
Vec4D[] cp = new Vec4D[4];
|
|
490
|
+
cp[0] = new Vec4D(o.xAxis.scale(r), 1);
|
|
491
|
+
cp[3] = cp[0].getInvertedXYZ();
|
|
492
|
+
cp[0].addXYZSelf(o.origin);
|
|
493
|
+
cp[3].addXYZSelf(o.origin);
|
|
494
|
+
cp[1] = new Vec4D(o.xAxis.add(o.yAxis).scaleSelf(r).addSelf(o.origin),
|
|
495
|
+
0.5f);
|
|
496
|
+
cp[2] = new Vec4D(o.xAxis.getInverted().addSelf(o.yAxis).scaleSelf(r)
|
|
497
|
+
.addSelf(o.origin), 0.5f);
|
|
498
|
+
|
|
499
|
+
float[] u = {
|
|
500
|
+
0, 0, 0, 0.5f, 1, 1, 1
|
|
501
|
+
};
|
|
502
|
+
return new BasicNurbsCurve(cp, u, 2);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Creates a {@link NurbsSurface} by swinging a profile {@link NurbsCurve}
|
|
507
|
+
* in the XZ plane around a trajectory curve in the XY plane. Both curves
|
|
508
|
+
* MUST be offset from the major axes (i.e. their control points should have
|
|
509
|
+
* non-zero coordinates for the Y coordinates of the profile curve and the Z
|
|
510
|
+
* coordinates of the trajectory).
|
|
511
|
+
*
|
|
512
|
+
* @param proj
|
|
513
|
+
* profile curve in XZ
|
|
514
|
+
* @param traj
|
|
515
|
+
* trajectory curve in XY
|
|
516
|
+
* @param alpha
|
|
517
|
+
* scale factor
|
|
518
|
+
* @return 3D NURBS surface
|
|
519
|
+
*/
|
|
520
|
+
public static NurbsSurface createSwungSurface(NurbsCurve proj,
|
|
521
|
+
NurbsCurve traj, float alpha) {
|
|
522
|
+
Vec4D[] cpProj = proj.getControlPoints();
|
|
523
|
+
Vec4D[] cpTraj = traj.getControlPoints();
|
|
524
|
+
|
|
525
|
+
// The NURBS Book, Piegl, p.455,456
|
|
526
|
+
// http://books.google.co.uk/books?id=7dqY5dyAwWkC&pg=PA455&lpg=PA455
|
|
527
|
+
// fixed Z handling (was wrong in original jgeom version)
|
|
528
|
+
Vec4D[][] cps = new Vec4D[cpProj.length][cpTraj.length];
|
|
529
|
+
for (int i = 0; i < cpProj.length; i++) {
|
|
530
|
+
for (int j = 0; j < cpTraj.length; j++) {
|
|
531
|
+
Vec4D cp = new Vec4D();
|
|
532
|
+
cp.x = cpProj[i].x * cpTraj[j].x * alpha;
|
|
533
|
+
cp.y = cpProj[i].y * cpTraj[j].y * alpha;
|
|
534
|
+
cp.z = (cpProj[i].z + cpTraj[j].z) * alpha;
|
|
535
|
+
cp.w = cpProj[i].w * cpTraj[j].w;
|
|
536
|
+
cps[i][j] = cp;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return new BasicNurbsSurface(new ControlNet(cps), proj.getKnots(),
|
|
540
|
+
traj.getKnots(), proj.getDegree(), traj.getDegree());
|
|
541
|
+
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Perform a linear extrusion of the given {@link NurbsCurve} along the
|
|
546
|
+
* supplied vector to produce a new {@link NurbsSurface}. The extrusion
|
|
547
|
+
* length is the length of the vector given.
|
|
548
|
+
*
|
|
549
|
+
* @param curve
|
|
550
|
+
* NURBS curve instance
|
|
551
|
+
* @param extrude
|
|
552
|
+
* a extrusion vector
|
|
553
|
+
* @return a NurbsSurface.
|
|
554
|
+
*/
|
|
555
|
+
public static NurbsSurface extrudeCurve(NurbsCurve curve, Vec3D extrude) {
|
|
556
|
+
|
|
557
|
+
// Curve and Surface Construction using Rational B-splines
|
|
558
|
+
// Piegl and Tiller CAD Vol 19 #9 November 1987 pp 485-498
|
|
559
|
+
KnotVector vKnot = new KnotVector(new float[] {
|
|
560
|
+
0f, 0f, 1f, 1f
|
|
561
|
+
}, 1);
|
|
562
|
+
|
|
563
|
+
Vec4D[][] cpoints = new Vec4D[curve.getControlPoints().length][2];
|
|
564
|
+
Vec4D[] curvePoints = curve.getControlPoints();
|
|
565
|
+
for (int i = 0; i < cpoints.length; i++) {
|
|
566
|
+
for (int j = 0; j < 2; j++) {
|
|
567
|
+
/*
|
|
568
|
+
* Change added 11/02/90 Steve Larkin : Have multiplied the term
|
|
569
|
+
* wcoord to the extrusion vector before adding to the curve
|
|
570
|
+
* coordinates. Not really sure this is the correct fix, but it
|
|
571
|
+
* works !
|
|
572
|
+
*/
|
|
573
|
+
Vec4D cp = new Vec4D();
|
|
574
|
+
cp.x = curvePoints[i].x + j * extrude.x;
|
|
575
|
+
cp.y = curvePoints[i].y + j * extrude.y;
|
|
576
|
+
cp.z = curvePoints[i].z + j * extrude.z;
|
|
577
|
+
cp.w = curvePoints[i].w;
|
|
578
|
+
cpoints[i][j] = cp;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
ControlNet cnet = new ControlNet(cpoints);
|
|
582
|
+
return new BasicNurbsSurface(cnet, curve.getKnots(), vKnot.getArray(),
|
|
583
|
+
curve.getDegree(), vKnot.getDegree());
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Interpolates a NurbCurve form the given Points using a global
|
|
588
|
+
* interpolation technique.
|
|
589
|
+
*
|
|
590
|
+
* @param points
|
|
591
|
+
* Points to interpolate
|
|
592
|
+
* @param degree
|
|
593
|
+
* degree of the interpolated NurbsCurve
|
|
594
|
+
* @return A NurbsCurve interpolating the given Points
|
|
595
|
+
* @throws InterpolationException
|
|
596
|
+
* thrown if interpolation failed or is not possible.
|
|
597
|
+
*/
|
|
598
|
+
public static NurbsCurve globalCurveInterpolation(Vec3D[] points, int degree)
|
|
599
|
+
throws InterpolationException {
|
|
600
|
+
try {
|
|
601
|
+
final int n = points.length;
|
|
602
|
+
final double[] A = new double[n * n];
|
|
603
|
+
|
|
604
|
+
final float[] uk = centripetal(points);
|
|
605
|
+
KnotVector uKnots = averaging(uk, degree);
|
|
606
|
+
for (int i = 0; i < n; i++) {
|
|
607
|
+
int span = uKnots.findSpan(uk[i]);
|
|
608
|
+
double[] tmp = uKnots.basisFunctions(span, uk[i]);
|
|
609
|
+
System.arraycopy(tmp, 0, A, i * n + span - degree, tmp.length);
|
|
610
|
+
}
|
|
611
|
+
final GMatrix a = new GMatrix(n, n, A);
|
|
612
|
+
final GVector perm = new GVector(n);
|
|
613
|
+
final GMatrix lu = new GMatrix(n, n);
|
|
614
|
+
a.computeLUD(lu, perm);
|
|
615
|
+
|
|
616
|
+
final Vec4D[] cps = new Vec4D[n];
|
|
617
|
+
for (int i = 0; i < cps.length; i++) {
|
|
618
|
+
cps[i] = new Vec4D(0, 0, 0, 1);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// x-ccordinate
|
|
622
|
+
final GVector b = new GVector(n);
|
|
623
|
+
for (int j = 0; j < n; j++) {
|
|
624
|
+
b.setElement(j, points[j].x);
|
|
625
|
+
}
|
|
626
|
+
final GVector sol = new GVector(n);
|
|
627
|
+
sol.backSolveLUD(lu, b, perm);
|
|
628
|
+
for (int j = 0; j < n; j++) {
|
|
629
|
+
cps[j].x = (float) sol.get(j);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// y-ccordinate
|
|
633
|
+
for (int j = 0; j < n; j++) {
|
|
634
|
+
b.setElement(j, points[j].y);
|
|
635
|
+
}
|
|
636
|
+
sol.zero();
|
|
637
|
+
sol.backSolveLUD(lu, b, perm);
|
|
638
|
+
for (int j = 0; j < n; j++) {
|
|
639
|
+
cps[j].y = (float) sol.get(j);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// z-ccordinate
|
|
643
|
+
for (int j = 0; j < n; j++) {
|
|
644
|
+
b.setElement(j, points[j].z);
|
|
645
|
+
}
|
|
646
|
+
sol.zero();
|
|
647
|
+
sol.backSolveLUD(lu, b, perm);
|
|
648
|
+
for (int j = 0; j < n; j++) {
|
|
649
|
+
cps[j].z = (float) sol.get(j);
|
|
650
|
+
}
|
|
651
|
+
return new BasicNurbsCurve(cps, uKnots);
|
|
652
|
+
} catch (SingularMatrixException ex) {
|
|
653
|
+
throw new InterpolationException(ex);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Interpolates a NurbsSurface from the given points using a gloabl
|
|
660
|
+
* interpolation technique.
|
|
661
|
+
*
|
|
662
|
+
* @param points
|
|
663
|
+
* Points arranged in a net (matrix) to interpolate
|
|
664
|
+
* @param uDegrees
|
|
665
|
+
* degree in u direction
|
|
666
|
+
* @param vDegrees
|
|
667
|
+
* degree in v direction
|
|
668
|
+
* @return A NurbsSurface interpolating the given points.
|
|
669
|
+
* @throws InterpolationException
|
|
670
|
+
* thrown if interpolation failed or is not possible.
|
|
671
|
+
*/
|
|
672
|
+
public static NurbsSurface globalSurfaceInterpolation(Vec3D[][] points,
|
|
673
|
+
int uDegrees, int vDegrees) throws InterpolationException {
|
|
674
|
+
final int n = points.length;
|
|
675
|
+
final int m = points[0].length;
|
|
676
|
+
float[][] uv = surfaceMeshParameters(points, n - 1, m - 1);
|
|
677
|
+
KnotVector u = averaging(uv[0], uDegrees);
|
|
678
|
+
KnotVector v = averaging(uv[1], vDegrees);
|
|
679
|
+
|
|
680
|
+
Vec4D[][] r = new Vec4D[m][n];
|
|
681
|
+
Vec3D[] tmp = new Vec3D[n];
|
|
682
|
+
for (int l = 0; l < m; l++) {
|
|
683
|
+
for (int i = 0; i < n; i++) {
|
|
684
|
+
tmp[i] = points[i][l];
|
|
685
|
+
}
|
|
686
|
+
try {
|
|
687
|
+
NurbsCurve curve = globalCurveInterpolation(tmp, uDegrees);
|
|
688
|
+
r[l] = curve.getControlPoints();
|
|
689
|
+
} catch (InterpolationException ex) {
|
|
690
|
+
for (int i = 0; i < tmp.length; i++) {
|
|
691
|
+
r[l][i] = new Vec4D(tmp[i], 1);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
Vec4D[][] cp = new Vec4D[n][m];
|
|
698
|
+
tmp = new Vec3D[m];
|
|
699
|
+
for (int i = 0; i < n; i++) {
|
|
700
|
+
for (int j = 0; j < m; j++) {
|
|
701
|
+
tmp[j] = r[j][i].to3D();
|
|
702
|
+
}
|
|
703
|
+
try {
|
|
704
|
+
NurbsCurve curve = globalCurveInterpolation(tmp, vDegrees);
|
|
705
|
+
cp[i] = curve.getControlPoints();
|
|
706
|
+
} catch (InterpolationException ex) {
|
|
707
|
+
for (int j = 0; j < tmp.length; j++) {
|
|
708
|
+
cp[i][j] = new Vec4D(tmp[j], 1);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
return new BasicNurbsSurface(new ControlNet(cp), u, v);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
private static void lineIntersect3D(Vec3D p0, Vec3D t0, Vec3D p2, Vec3D t2,
|
|
717
|
+
Vec3D out0, Vec3D out2) {
|
|
718
|
+
Vec3D v02 = p0.sub(p2);
|
|
719
|
+
|
|
720
|
+
double a = t0.dot(t0);
|
|
721
|
+
double b = t0.dot(t2);
|
|
722
|
+
double c = t2.dot(t2);
|
|
723
|
+
double d = t0.dot(v02);
|
|
724
|
+
double e = t2.dot(v02);
|
|
725
|
+
double denom = a * c - b * b;
|
|
726
|
+
|
|
727
|
+
double mu0, mu2;
|
|
728
|
+
|
|
729
|
+
if (denom < MathUtils.EPS) {
|
|
730
|
+
mu0 = 0;
|
|
731
|
+
mu2 = b > c ? d / b : e / c;
|
|
732
|
+
} else {
|
|
733
|
+
mu0 = (b * e - c * d) / denom;
|
|
734
|
+
mu2 = (a * e - b * d) / denom;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
out0.set(t0.scale((float) mu0).addSelf(p0));
|
|
738
|
+
out2.set(t2.scale((float) mu2).addSelf(p2));
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
private static void pointToLine3D(ReadonlyVec3D p, ReadonlyVec3D t,
|
|
742
|
+
Vec3D top, Vec3D out) {
|
|
743
|
+
Vec3D dir = top.sub(p);
|
|
744
|
+
float hyp = dir.magnitude();
|
|
745
|
+
out.set(p.add(t.scale(t.dot(dir.normalize()) * hyp)));
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
private static float[][] surfaceMeshParameters(Vec3D points[][], int n,
|
|
749
|
+
int m) {
|
|
750
|
+
final float[][] res = new float[2][];
|
|
751
|
+
int num = m + 1;
|
|
752
|
+
final float[] cds = new float[(n + 1) * (m + 1)];
|
|
753
|
+
final float[] uk = new float[n + 1];
|
|
754
|
+
uk[n] = 1;
|
|
755
|
+
for (int l = 0; l <= m; l++) {
|
|
756
|
+
float total = 0;
|
|
757
|
+
for (int k = 1; k <= n; k++) {
|
|
758
|
+
cds[k] = points[k][l].distanceTo(points[k - 1][l]);
|
|
759
|
+
total += cds[k];
|
|
760
|
+
}
|
|
761
|
+
if (total == 0) {
|
|
762
|
+
num = num - 1;
|
|
763
|
+
} else {
|
|
764
|
+
float d = 0;
|
|
765
|
+
total = 1f / total;
|
|
766
|
+
for (int k = 1; k <= n; k++) {
|
|
767
|
+
d += cds[k];
|
|
768
|
+
uk[k] += d * total;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (num == 0) {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
float inum = 1f / num;
|
|
776
|
+
for (int k = 1; k < n; k++) {
|
|
777
|
+
uk[k] *= inum;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
num = n + 1;
|
|
781
|
+
final float[] vk = new float[m + 1];
|
|
782
|
+
vk[m] = 1;
|
|
783
|
+
for (int l = 0; l <= n; l++) {
|
|
784
|
+
float total = 0;
|
|
785
|
+
Vec3D[] pl = points[l];
|
|
786
|
+
for (int k = 1; k <= m; k++) {
|
|
787
|
+
cds[k] = pl[k].distanceTo(pl[k - 1]);
|
|
788
|
+
total += cds[k];
|
|
789
|
+
}
|
|
790
|
+
if (total == 0) {
|
|
791
|
+
num = num - 1;
|
|
792
|
+
} else {
|
|
793
|
+
float d = 0;
|
|
794
|
+
total = 1f / total;
|
|
795
|
+
for (int k = 1; k <= m; k++) {
|
|
796
|
+
d += cds[k];
|
|
797
|
+
vk[k] += d * total;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
if (num == 0) {
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
804
|
+
inum = 1f / num;
|
|
805
|
+
for (int k = 1; k < m; k++) {
|
|
806
|
+
vk[k] *= inum;
|
|
807
|
+
}
|
|
808
|
+
res[0] = uk;
|
|
809
|
+
res[1] = vk;
|
|
810
|
+
return res;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private NurbsCreator() {
|
|
814
|
+
}
|
|
815
|
+
}
|