toxiclibs 0.4.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +16 -0
- data/.mvn/extensions.xml +8 -0
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +7 -0
- data/COPYING.md +14 -0
- data/Gemfile +10 -0
- data/LICENSE +675 -0
- data/README.md +9 -7
- data/Rakefile +25 -81
- data/examples/README.md +5 -0
- 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/ReplicaBold.ttf +0 -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 +74 -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 +43 -0
- data/examples/physics_type.rb +77 -0
- data/examples/povmesh/data/mask.jpg +0 -0
- data/examples/povmesh/ftest.rb +59 -0
- data/examples/povmesh/mesh_align.rb +47 -0
- data/examples/povmesh/tentacle.rb +71 -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/examples/spherical_harmonics_mesh.rb +50 -0
- data/examples/test_rect.rb +32 -0
- data/lib/toxiclibs.jar +0 -0
- data/lib/toxiclibs.rb +72 -22
- data/lib/toxiclibs/version.rb +1 -1
- data/pom.rb +63 -0
- data/pom.xml +124 -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/audio/AudioBuffer.java +229 -0
- data/src/toxi/audio/AudioSource.java +288 -0
- data/src/toxi/audio/DecompressInputStream.java +159 -0
- data/src/toxi/audio/IIRFilter.java +197 -0
- data/src/toxi/audio/JOALUtil.java +388 -0
- data/src/toxi/audio/MultiTimbralManager.java +162 -0
- data/src/toxi/audio/SoundListener.java +154 -0
- data/src/toxi/audio/SynthUtil.java +109 -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 +127 -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 +28 -0
- metadata +442 -31
@@ -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
|
+
}
|