toxiclibs 0.2-java → 0.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -0
  3. data/CHANGELOG.md +4 -0
  4. data/LICENSE +675 -0
  5. data/README.md +12 -5
  6. data/Rakefile +25 -82
  7. data/examples/attract_repel/attract_repel.rb +30 -0
  8. data/examples/attract_repel/attractor.rb +23 -0
  9. data/examples/attract_repel/particle.rb +27 -0
  10. data/examples/data/ti_yong.png +0 -0
  11. data/examples/force_directed/cluster.rb +76 -0
  12. data/examples/force_directed/force_directed_graph.rb +92 -0
  13. data/examples/force_directed/node.rb +26 -0
  14. data/examples/gray_scott_image.rb +75 -0
  15. data/examples/gray_scott_tone_map.rb +77 -0
  16. data/examples/implicit.rb +139 -0
  17. data/examples/inflate_mesh.rb +89 -0
  18. data/examples/model_align.rb +44 -0
  19. data/examples/povmesh/ftest.rb +46 -0
  20. data/examples/povmesh/tentacle.rb +73 -0
  21. data/examples/simple_cluster/cluster.rb +47 -0
  22. data/examples/simple_cluster/node.rb +27 -0
  23. data/examples/simple_cluster/simple_cluster.rb +60 -0
  24. data/examples/soft_body/blanket.rb +45 -0
  25. data/examples/soft_body/connection.rb +16 -0
  26. data/examples/soft_body/particle.rb +22 -0
  27. data/examples/soft_body/soft_body_square_adapted.rb +55 -0
  28. data/lib/toxiclibs.jar +0 -0
  29. data/lib/toxiclibs.rb +91 -32
  30. data/lib/toxiclibs/version.rb +1 -1
  31. data/pom.xml +122 -0
  32. data/src/com/toxi/net/ClientListener.java +41 -0
  33. data/src/com/toxi/net/ServerListener.java +70 -0
  34. data/src/com/toxi/net/ServerListenerAdapter.java +47 -0
  35. data/src/com/toxi/net/ServerState.java +18 -0
  36. data/src/com/toxi/net/UDPConnection.java +66 -0
  37. data/src/com/toxi/net/UDPSyncClient.java +81 -0
  38. data/src/com/toxi/net/UDPSyncServer.java +450 -0
  39. data/src/com/toxi/nio/UDPClient.java +121 -0
  40. data/src/com/toxi/nio/UDPClientState.java +32 -0
  41. data/src/com/toxi/nio/UDPServer.java +129 -0
  42. data/src/toxi/color/AccessCriteria.java +114 -0
  43. data/src/toxi/color/AlphaAccessor.java +67 -0
  44. data/src/toxi/color/CMYKAccessor.java +122 -0
  45. data/src/toxi/color/CMYKDistanceProxy.java +40 -0
  46. data/src/toxi/color/ColorGradient.java +260 -0
  47. data/src/toxi/color/ColorList.java +699 -0
  48. data/src/toxi/color/ColorRange.java +671 -0
  49. data/src/toxi/color/ColorTheme.java +163 -0
  50. data/src/toxi/color/DistanceProxy.java +44 -0
  51. data/src/toxi/color/HSVAccessor.java +113 -0
  52. data/src/toxi/color/HSVDistanceProxy.java +40 -0
  53. data/src/toxi/color/HistEntry.java +85 -0
  54. data/src/toxi/color/Histogram.java +185 -0
  55. data/src/toxi/color/Hue.java +249 -0
  56. data/src/toxi/color/LuminanceAccessor.java +78 -0
  57. data/src/toxi/color/NamedColor.java +935 -0
  58. data/src/toxi/color/ProximityComparator.java +70 -0
  59. data/src/toxi/color/RGBAccessor.java +113 -0
  60. data/src/toxi/color/RGBDistanceProxy.java +41 -0
  61. data/src/toxi/color/ReadonlyTColor.java +296 -0
  62. data/src/toxi/color/TColor.java +1677 -0
  63. data/src/toxi/color/TColorAdapter.java +68 -0
  64. data/src/toxi/color/ToneMap.java +218 -0
  65. data/src/toxi/color/theory/AnalogousStrategy.java +140 -0
  66. data/src/toxi/color/theory/ColorTheoryRegistry.java +139 -0
  67. data/src/toxi/color/theory/ColorTheoryStrategy.java +56 -0
  68. data/src/toxi/color/theory/ComplementaryStrategy.java +111 -0
  69. data/src/toxi/color/theory/CompoundTheoryStrategy.java +143 -0
  70. data/src/toxi/color/theory/LeftSplitComplementaryStrategy.java +82 -0
  71. data/src/toxi/color/theory/MonochromeTheoryStrategy.java +103 -0
  72. data/src/toxi/color/theory/RightSplitComplementaryStrategy.java +82 -0
  73. data/src/toxi/color/theory/SingleComplementStrategy.java +76 -0
  74. data/src/toxi/color/theory/SplitComplementaryStrategy.java +77 -0
  75. data/src/toxi/color/theory/TetradTheoryStrategy.java +114 -0
  76. data/src/toxi/color/theory/TriadTheoryStrategy.java +77 -0
  77. data/src/toxi/data/csv/CSVAdapter.java +74 -0
  78. data/src/toxi/data/csv/CSVFieldMapper.java +212 -0
  79. data/src/toxi/data/csv/CSVListener.java +61 -0
  80. data/src/toxi/data/csv/CSVParser.java +202 -0
  81. data/src/toxi/data/feeds/AtomAuthor.java +49 -0
  82. data/src/toxi/data/feeds/AtomContent.java +50 -0
  83. data/src/toxi/data/feeds/AtomEntry.java +111 -0
  84. data/src/toxi/data/feeds/AtomFeed.java +129 -0
  85. data/src/toxi/data/feeds/AtomLink.java +62 -0
  86. data/src/toxi/data/feeds/RSSChannel.java +88 -0
  87. data/src/toxi/data/feeds/RSSEnclosure.java +60 -0
  88. data/src/toxi/data/feeds/RSSFeed.java +99 -0
  89. data/src/toxi/data/feeds/RSSItem.java +104 -0
  90. data/src/toxi/data/feeds/util/EntityStripper.java +2480 -0
  91. data/src/toxi/data/feeds/util/Iso8601DateAdapter.java +101 -0
  92. data/src/toxi/data/feeds/util/Rfc822DateAdapter.java +93 -0
  93. data/src/toxi/geom/AABB.java +658 -0
  94. data/src/toxi/geom/Axis3D.java +116 -0
  95. data/src/toxi/geom/AxisAlignedCylinder.java +163 -0
  96. data/src/toxi/geom/BernsteinPolynomial.java +94 -0
  97. data/src/toxi/geom/BezierCurve2D.java +159 -0
  98. data/src/toxi/geom/BezierCurve3D.java +148 -0
  99. data/src/toxi/geom/BooleanShapeBuilder.java +185 -0
  100. data/src/toxi/geom/BoxIntersector.java +52 -0
  101. data/src/toxi/geom/Circle.java +230 -0
  102. data/src/toxi/geom/CircleIntersector.java +85 -0
  103. data/src/toxi/geom/Cone.java +150 -0
  104. data/src/toxi/geom/ConvexPolygonClipper.java +136 -0
  105. data/src/toxi/geom/CoordinateExtractor.java +16 -0
  106. data/src/toxi/geom/Ellipse.java +250 -0
  107. data/src/toxi/geom/GMatrix.java +2599 -0
  108. data/src/toxi/geom/GVector.java +833 -0
  109. data/src/toxi/geom/GlobalGridTesselator.java +54 -0
  110. data/src/toxi/geom/GridTesselator.java +108 -0
  111. data/src/toxi/geom/Intersector2D.java +49 -0
  112. data/src/toxi/geom/Intersector3D.java +51 -0
  113. data/src/toxi/geom/IsectData2D.java +103 -0
  114. data/src/toxi/geom/IsectData3D.java +103 -0
  115. data/src/toxi/geom/Line2D.java +534 -0
  116. data/src/toxi/geom/Line3D.java +471 -0
  117. data/src/toxi/geom/LineStrip2D.java +430 -0
  118. data/src/toxi/geom/LineStrip3D.java +230 -0
  119. data/src/toxi/geom/LocalGridTesselator.java +57 -0
  120. data/src/toxi/geom/Matrix3d.java +3048 -0
  121. data/src/toxi/geom/Matrix4f.java +3446 -0
  122. data/src/toxi/geom/Matrix4x4.java +1076 -0
  123. data/src/toxi/geom/MatrixSizeException.java +58 -0
  124. data/src/toxi/geom/OctreeVisitor.java +44 -0
  125. data/src/toxi/geom/Origin3D.java +148 -0
  126. data/src/toxi/geom/Plane.java +293 -0
  127. data/src/toxi/geom/PlaneIntersector.java +57 -0
  128. data/src/toxi/geom/PointCloud3D.java +253 -0
  129. data/src/toxi/geom/PointOctree.java +502 -0
  130. data/src/toxi/geom/PointQuadtree.java +375 -0
  131. data/src/toxi/geom/Polygon2D.java +1038 -0
  132. data/src/toxi/geom/PolygonClipper2D.java +45 -0
  133. data/src/toxi/geom/PolygonTesselator.java +20 -0
  134. data/src/toxi/geom/QuadtreeVisitor.java +44 -0
  135. data/src/toxi/geom/Quaternion.java +641 -0
  136. data/src/toxi/geom/Ray2D.java +146 -0
  137. data/src/toxi/geom/Ray3D.java +150 -0
  138. data/src/toxi/geom/Ray3DIntersector.java +75 -0
  139. data/src/toxi/geom/ReadonlyVec2D.java +575 -0
  140. data/src/toxi/geom/ReadonlyVec3D.java +628 -0
  141. data/src/toxi/geom/ReadonlyVec4D.java +431 -0
  142. data/src/toxi/geom/Rect.java +720 -0
  143. data/src/toxi/geom/Reflector3D.java +58 -0
  144. data/src/toxi/geom/Shape2D.java +94 -0
  145. data/src/toxi/geom/Shape3D.java +42 -0
  146. data/src/toxi/geom/SingularMatrixException.java +57 -0
  147. data/src/toxi/geom/SpatialBins.java +182 -0
  148. data/src/toxi/geom/SpatialIndex.java +61 -0
  149. data/src/toxi/geom/Sphere.java +224 -0
  150. data/src/toxi/geom/SphereIntersectorReflector.java +196 -0
  151. data/src/toxi/geom/Spline2D.java +349 -0
  152. data/src/toxi/geom/Spline3D.java +351 -0
  153. data/src/toxi/geom/SutherlandHodgemanClipper.java +151 -0
  154. data/src/toxi/geom/Triangle2D.java +422 -0
  155. data/src/toxi/geom/Triangle3D.java +456 -0
  156. data/src/toxi/geom/TriangleIntersector.java +105 -0
  157. data/src/toxi/geom/Vec2D.java +1328 -0
  158. data/src/toxi/geom/Vec3D.java +1832 -0
  159. data/src/toxi/geom/Vec4D.java +985 -0
  160. data/src/toxi/geom/VecMathUtil.java +100 -0
  161. data/src/toxi/geom/XAxisCylinder.java +64 -0
  162. data/src/toxi/geom/YAxisCylinder.java +65 -0
  163. data/src/toxi/geom/ZAxisCylinder.java +64 -0
  164. data/src/toxi/geom/mesh/BezierPatch.java +200 -0
  165. data/src/toxi/geom/mesh/BoxSelector.java +62 -0
  166. data/src/toxi/geom/mesh/DefaultSTLColorModel.java +67 -0
  167. data/src/toxi/geom/mesh/DefaultSelector.java +50 -0
  168. data/src/toxi/geom/mesh/Face.java +176 -0
  169. data/src/toxi/geom/mesh/LaplacianSmooth.java +80 -0
  170. data/src/toxi/geom/mesh/MaterialiseSTLColorModel.java +150 -0
  171. data/src/toxi/geom/mesh/Mesh3D.java +224 -0
  172. data/src/toxi/geom/mesh/MeshIntersector.java +91 -0
  173. data/src/toxi/geom/mesh/OBJWriter.java +194 -0
  174. data/src/toxi/geom/mesh/PLYWriter.java +167 -0
  175. data/src/toxi/geom/mesh/PlaneSelector.java +90 -0
  176. data/src/toxi/geom/mesh/STLColorModel.java +54 -0
  177. data/src/toxi/geom/mesh/STLReader.java +185 -0
  178. data/src/toxi/geom/mesh/STLWriter.java +323 -0
  179. data/src/toxi/geom/mesh/SphereFunction.java +156 -0
  180. data/src/toxi/geom/mesh/SphericalHarmonics.java +110 -0
  181. data/src/toxi/geom/mesh/SuperEllipsoid.java +110 -0
  182. data/src/toxi/geom/mesh/SurfaceFunction.java +75 -0
  183. data/src/toxi/geom/mesh/SurfaceMeshBuilder.java +149 -0
  184. data/src/toxi/geom/mesh/Terrain.java +451 -0
  185. data/src/toxi/geom/mesh/TriangleMesh.java +1201 -0
  186. data/src/toxi/geom/mesh/Vertex.java +78 -0
  187. data/src/toxi/geom/mesh/VertexSelector.java +193 -0
  188. data/src/toxi/geom/mesh/WEFace.java +100 -0
  189. data/src/toxi/geom/mesh/WEMeshFilterStrategy.java +51 -0
  190. data/src/toxi/geom/mesh/WETriangleMesh.java +761 -0
  191. data/src/toxi/geom/mesh/WEVertex.java +134 -0
  192. data/src/toxi/geom/mesh/WingedEdge.java +115 -0
  193. data/src/toxi/geom/mesh/subdiv/CentroidSubdiv.java +37 -0
  194. data/src/toxi/geom/mesh/subdiv/DisplacementSubdivision.java +85 -0
  195. data/src/toxi/geom/mesh/subdiv/DualDisplacementSubdivision.java +94 -0
  196. data/src/toxi/geom/mesh/subdiv/DualSubdivision.java +49 -0
  197. data/src/toxi/geom/mesh/subdiv/EdgeLengthComparator.java +50 -0
  198. data/src/toxi/geom/mesh/subdiv/FaceCountComparator.java +51 -0
  199. data/src/toxi/geom/mesh/subdiv/MidpointDisplacementSubdivision.java +80 -0
  200. data/src/toxi/geom/mesh/subdiv/MidpointSubdiv.java +42 -0
  201. data/src/toxi/geom/mesh/subdiv/MidpointSubdivision.java +48 -0
  202. data/src/toxi/geom/mesh/subdiv/NewSubdivStrategy.java +23 -0
  203. data/src/toxi/geom/mesh/subdiv/NormalDisplacementSubdivision.java +74 -0
  204. data/src/toxi/geom/mesh/subdiv/SubdivisionStrategy.java +83 -0
  205. data/src/toxi/geom/mesh/subdiv/TriSubdivision.java +51 -0
  206. data/src/toxi/geom/mesh2d/DelaunayTriangle.java +222 -0
  207. data/src/toxi/geom/mesh2d/DelaunayTriangulation.java +327 -0
  208. data/src/toxi/geom/mesh2d/DelaunayVertex.java +560 -0
  209. data/src/toxi/geom/mesh2d/Voronoi.java +149 -0
  210. data/src/toxi/geom/nurbs/BasicNurbsCurve.java +210 -0
  211. data/src/toxi/geom/nurbs/BasicNurbsSurface.java +233 -0
  212. data/src/toxi/geom/nurbs/ControlNet.java +148 -0
  213. data/src/toxi/geom/nurbs/CurveCreator.java +112 -0
  214. data/src/toxi/geom/nurbs/CurveUtils.java +259 -0
  215. data/src/toxi/geom/nurbs/InterpolationException.java +65 -0
  216. data/src/toxi/geom/nurbs/KnotVector.java +333 -0
  217. data/src/toxi/geom/nurbs/NurbsCreator.java +815 -0
  218. data/src/toxi/geom/nurbs/NurbsCurve.java +120 -0
  219. data/src/toxi/geom/nurbs/NurbsMeshCreator.java +145 -0
  220. data/src/toxi/geom/nurbs/NurbsSurface.java +147 -0
  221. data/src/toxi/image/util/Filter8bit.java +331 -0
  222. data/src/toxi/image/util/TiledFrameExporter.java +162 -0
  223. data/src/toxi/math/BezierInterpolation.java +102 -0
  224. data/src/toxi/math/CircularInterpolation.java +88 -0
  225. data/src/toxi/math/CosineInterpolation.java +51 -0
  226. data/src/toxi/math/DecimatedInterpolation.java +77 -0
  227. data/src/toxi/math/ExponentialInterpolation.java +68 -0
  228. data/src/toxi/math/InterpolateStrategy.java +60 -0
  229. data/src/toxi/math/Interpolation2D.java +93 -0
  230. data/src/toxi/math/LinearInterpolation.java +46 -0
  231. data/src/toxi/math/MathUtils.java +990 -0
  232. data/src/toxi/math/NonLinearScaleMap.java +101 -0
  233. data/src/toxi/math/ScaleMap.java +183 -0
  234. data/src/toxi/math/SigmoidInterpolation.java +78 -0
  235. data/src/toxi/math/SinCosLUT.java +141 -0
  236. data/src/toxi/math/ThresholdInterpolation.java +58 -0
  237. data/src/toxi/math/ZoomLensInterpolation.java +126 -0
  238. data/src/toxi/math/conversion/UnitTranslator.java +161 -0
  239. data/src/toxi/math/noise/PerlinNoise.java +281 -0
  240. data/src/toxi/math/noise/SimplexNoise.java +542 -0
  241. data/src/toxi/math/waves/AMFMSineWave.java +143 -0
  242. data/src/toxi/math/waves/AbstractWave.java +248 -0
  243. data/src/toxi/math/waves/ConstantWave.java +48 -0
  244. data/src/toxi/math/waves/FMHarmonicSquareWave.java +155 -0
  245. data/src/toxi/math/waves/FMSawtoothWave.java +144 -0
  246. data/src/toxi/math/waves/FMSineWave.java +142 -0
  247. data/src/toxi/math/waves/FMSquareWave.java +143 -0
  248. data/src/toxi/math/waves/FMTriangleWave.java +126 -0
  249. data/src/toxi/math/waves/SineWave.java +81 -0
  250. data/src/toxi/math/waves/Wave2D.java +68 -0
  251. data/src/toxi/math/waves/WaveState.java +69 -0
  252. data/src/toxi/music/scale/AbstractScale.java +117 -0
  253. data/src/toxi/music/scale/GenericScale.java +66 -0
  254. data/src/toxi/music/scale/MajorScale.java +41 -0
  255. data/src/toxi/newmesh/AttributedEdge.java +106 -0
  256. data/src/toxi/newmesh/AttributedFace.java +63 -0
  257. data/src/toxi/newmesh/IndexedTriangleMesh.java +809 -0
  258. data/src/toxi/newmesh/MeshAttributeCompiler.java +45 -0
  259. data/src/toxi/newmesh/MeshFaceNormalCompiler.java +52 -0
  260. data/src/toxi/newmesh/MeshUVCompiler.java +52 -0
  261. data/src/toxi/newmesh/MeshVertexColorCompiler.java +49 -0
  262. data/src/toxi/newmesh/MeshVertexCompiler.java +54 -0
  263. data/src/toxi/newmesh/MeshVertexNormalCompiler.java +55 -0
  264. data/src/toxi/newmesh/SpatialIndex.java +78 -0
  265. data/src/toxi/physics2d/ParticlePath2D.java +100 -0
  266. data/src/toxi/physics2d/ParticleString2D.java +184 -0
  267. data/src/toxi/physics2d/PullBackSpring2D.java +51 -0
  268. data/src/toxi/physics2d/VerletConstrainedSpring2D.java +89 -0
  269. data/src/toxi/physics2d/VerletMinDistanceSpring2D.java +57 -0
  270. data/src/toxi/physics2d/VerletParticle2D.java +457 -0
  271. data/src/toxi/physics2d/VerletPhysics2D.java +448 -0
  272. data/src/toxi/physics2d/VerletSpring2D.java +181 -0
  273. data/src/toxi/physics2d/behaviors/AttractionBehavior2D.java +212 -0
  274. data/src/toxi/physics2d/behaviors/ConstantForceBehavior2D.java +112 -0
  275. data/src/toxi/physics2d/behaviors/GravityBehavior2D.java +61 -0
  276. data/src/toxi/physics2d/behaviors/ParticleBehavior2D.java +66 -0
  277. data/src/toxi/physics2d/constraints/AngularConstraint.java +83 -0
  278. data/src/toxi/physics2d/constraints/AxisConstraint.java +71 -0
  279. data/src/toxi/physics2d/constraints/CircularConstraint.java +69 -0
  280. data/src/toxi/physics2d/constraints/MaxConstraint.java +66 -0
  281. data/src/toxi/physics2d/constraints/MinConstraint.java +66 -0
  282. data/src/toxi/physics2d/constraints/ParticleConstraint2D.java +47 -0
  283. data/src/toxi/physics2d/constraints/PolygonConstraint.java +93 -0
  284. data/src/toxi/physics2d/constraints/RectConstraint.java +114 -0
  285. data/src/toxi/physics3d/ParticlePath3D.java +100 -0
  286. data/src/toxi/physics3d/ParticleString3D.java +184 -0
  287. data/src/toxi/physics3d/PullBackSpring3D.java +50 -0
  288. data/src/toxi/physics3d/VerletConstrainedSpring3D.java +88 -0
  289. data/src/toxi/physics3d/VerletMinDistanceSpring3D.java +56 -0
  290. data/src/toxi/physics3d/VerletParticle3D.java +385 -0
  291. data/src/toxi/physics3d/VerletPhysics3D.java +417 -0
  292. data/src/toxi/physics3d/VerletSpring3D.java +180 -0
  293. data/src/toxi/physics3d/behaviors/AttractionBehavior3D.java +182 -0
  294. data/src/toxi/physics3d/behaviors/ConstantForceBehavior3D.java +92 -0
  295. data/src/toxi/physics3d/behaviors/GravityBehavior3D.java +61 -0
  296. data/src/toxi/physics3d/behaviors/ParticleBehavior3D.java +52 -0
  297. data/src/toxi/physics3d/constraints/AxisConstraint.java +68 -0
  298. data/src/toxi/physics3d/constraints/BoxConstraint.java +121 -0
  299. data/src/toxi/physics3d/constraints/CylinderConstraint.java +87 -0
  300. data/src/toxi/physics3d/constraints/MaxConstraint.java +65 -0
  301. data/src/toxi/physics3d/constraints/MinConstraint.java +65 -0
  302. data/src/toxi/physics3d/constraints/ParticleConstraint3D.java +49 -0
  303. data/src/toxi/physics3d/constraints/PlaneConstraint.java +78 -0
  304. data/src/toxi/physics3d/constraints/SoftBoxConstraint.java +87 -0
  305. data/src/toxi/physics3d/constraints/SphereConstraint.java +108 -0
  306. data/src/toxi/processing/ArrowModifier.java +116 -0
  307. data/src/toxi/processing/DashedLineModifier.java +48 -0
  308. data/src/toxi/processing/DeltaOrientationMapper.java +57 -0
  309. data/src/toxi/processing/Line2DRenderModifier.java +18 -0
  310. data/src/toxi/processing/MeshToVBO.java +94 -0
  311. data/src/toxi/processing/NormalMapper.java +18 -0
  312. data/src/toxi/processing/POVInterface.java +121 -0
  313. data/src/toxi/processing/POVMesh.java +219 -0
  314. data/src/toxi/processing/POVWriter.java +460 -0
  315. data/src/toxi/processing/RCOpaque.java +77 -0
  316. data/src/toxi/processing/RCTransp.java +78 -0
  317. data/src/toxi/processing/TextureBuilder.java +232 -0
  318. data/src/toxi/processing/Textures.java +110 -0
  319. data/src/toxi/processing/ToxiclibsSupport.java +1239 -0
  320. data/src/toxi/processing/Tracing.java +25 -0
  321. data/src/toxi/processing/XYZNormalMapper.java +30 -0
  322. data/src/toxi/sim/automata/CAMatrix.java +297 -0
  323. data/src/toxi/sim/automata/CARule.java +76 -0
  324. data/src/toxi/sim/automata/CARule2D.java +354 -0
  325. data/src/toxi/sim/automata/CAWolfram1D.java +309 -0
  326. data/src/toxi/sim/automata/EvolvableMatrix.java +61 -0
  327. data/src/toxi/sim/automata/MatrixEvolver.java +42 -0
  328. data/src/toxi/sim/dla/BottomUpOrder.java +76 -0
  329. data/src/toxi/sim/dla/DLA.java +497 -0
  330. data/src/toxi/sim/dla/DLAConfiguration.java +364 -0
  331. data/src/toxi/sim/dla/DLAEventAdapter.java +64 -0
  332. data/src/toxi/sim/dla/DLAEventListener.java +57 -0
  333. data/src/toxi/sim/dla/DLAGuideLines.java +219 -0
  334. data/src/toxi/sim/dla/DLAParticle.java +102 -0
  335. data/src/toxi/sim/dla/DLASegment.java +88 -0
  336. data/src/toxi/sim/dla/PipelineOrder.java +50 -0
  337. data/src/toxi/sim/dla/RadialDistanceOrder.java +92 -0
  338. data/src/toxi/sim/erosion/ErosionFunction.java +122 -0
  339. data/src/toxi/sim/erosion/TalusAngleErosion.java +145 -0
  340. data/src/toxi/sim/erosion/ThermalErosion.java +75 -0
  341. data/src/toxi/sim/fluids/FluidSolver2D.java +762 -0
  342. data/src/toxi/sim/fluids/FluidSolver3D.java +326 -0
  343. data/src/toxi/sim/grayscott/GrayScott.java +469 -0
  344. data/src/toxi/util/DateUtils.java +141 -0
  345. data/src/toxi/util/FileSequenceDescriptor.java +181 -0
  346. data/src/toxi/util/FileUtils.java +467 -0
  347. data/src/toxi/util/datatypes/ArraySet.java +128 -0
  348. data/src/toxi/util/datatypes/ArrayUtil.java +404 -0
  349. data/src/toxi/util/datatypes/BiasedDoubleRange.java +141 -0
  350. data/src/toxi/util/datatypes/BiasedFloatRange.java +141 -0
  351. data/src/toxi/util/datatypes/BiasedIntegerRange.java +141 -0
  352. data/src/toxi/util/datatypes/DoubleRange.java +251 -0
  353. data/src/toxi/util/datatypes/FloatRange.java +251 -0
  354. data/src/toxi/util/datatypes/GenericSet.java +215 -0
  355. data/src/toxi/util/datatypes/IntegerRange.java +247 -0
  356. data/src/toxi/util/datatypes/IntegerSet.java +149 -0
  357. data/src/toxi/util/datatypes/ItemIndex.java +72 -0
  358. data/src/toxi/util/datatypes/SingletonRegistry.java +91 -0
  359. data/src/toxi/util/datatypes/TypedProperties.java +291 -0
  360. data/src/toxi/util/datatypes/UndirectedGraph.java +134 -0
  361. data/src/toxi/util/datatypes/UniqueItemIndex.java +223 -0
  362. data/src/toxi/util/datatypes/WeightedRandomEntry.java +76 -0
  363. data/src/toxi/util/datatypes/WeightedRandomSet.java +125 -0
  364. data/src/toxi/util/events/EventDispatcher.java +86 -0
  365. data/src/toxi/volume/AdditiveBrush.java +19 -0
  366. data/src/toxi/volume/ArrayIsoSurface.java +297 -0
  367. data/src/toxi/volume/BoxBrush.java +100 -0
  368. data/src/toxi/volume/BrushMode.java +16 -0
  369. data/src/toxi/volume/HashIsoSurface.java +354 -0
  370. data/src/toxi/volume/IsoSurface.java +59 -0
  371. data/src/toxi/volume/MarchingCubesIndex.java +312 -0
  372. data/src/toxi/volume/MeshLatticeBuilder.java +358 -0
  373. data/src/toxi/volume/MeshVoxelizer.java +216 -0
  374. data/src/toxi/volume/MultiplyBrush.java +20 -0
  375. data/src/toxi/volume/PeakBrush.java +21 -0
  376. data/src/toxi/volume/ReplaceBrush.java +19 -0
  377. data/src/toxi/volume/RoundBrush.java +113 -0
  378. data/src/toxi/volume/VolumetricBrush.java +160 -0
  379. data/src/toxi/volume/VolumetricHashMap.java +179 -0
  380. data/src/toxi/volume/VolumetricSpace.java +195 -0
  381. data/src/toxi/volume/VolumetricSpaceArray.java +214 -0
  382. data/toxiclibs.gemspec +34 -0
  383. metadata +424 -27
@@ -0,0 +1,375 @@
1
+ /*
2
+ * __ .__ .__ ._____.
3
+ * _/ |_ _______ __|__| ____ | | |__\_ |__ ______
4
+ * \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
5
+ * | | ( <_> > <| \ \___| |_| || \_\ \\___ \
6
+ * |__| \____/__/\_ \__|\___ >____/__||___ /____ >
7
+ * \/ \/ \/ \/
8
+ *
9
+ * Copyright (c) 2006-2011 Karsten Schmidt
10
+ *
11
+ * This library is free software; you can redistribute it and/or
12
+ * modify it under the terms of the GNU Lesser General Public
13
+ * License as published by the Free Software Foundation; either
14
+ * version 2.1 of the License, or (at your option) any later version.
15
+ *
16
+ * http://creativecommons.org/licenses/LGPL/2.1/
17
+ *
18
+ * This library is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
+ * Lesser General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU Lesser General Public
24
+ * License along with this library; if not, write to the Free Software
25
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26
+ */
27
+
28
+ package toxi.geom;
29
+
30
+ import java.util.ArrayList;
31
+ import java.util.List;
32
+
33
+ /**
34
+ * Implements a spatial subdivision tree to work efficiently with large numbers
35
+ * of 2D particles. This quadtree can only be used for particle type objects and
36
+ * does NOT support 2D mesh geometry as other forms of quadtree might do.
37
+ *
38
+ * For further reference also see the QuadtreeDemo in the /examples folder.
39
+ *
40
+ */
41
+ public class PointQuadtree extends Rect implements SpatialIndex<Vec2D> {
42
+
43
+ /**
44
+ *
45
+ */
46
+ public enum Type {
47
+
48
+ /**
49
+ *
50
+ */
51
+ EMPTY,
52
+
53
+ /**
54
+ *
55
+ */
56
+ BRANCH,
57
+
58
+ /**
59
+ *
60
+ */
61
+ LEAF;
62
+ }
63
+
64
+ private PointQuadtree parent;
65
+ private PointQuadtree childNW, childNE, childSW, childSE;
66
+
67
+ private Type type;
68
+
69
+ private Vec2D value;
70
+ private float mx, my;
71
+
72
+ /**
73
+ *
74
+ * @param x
75
+ * @param y
76
+ * @param w
77
+ * @param h
78
+ */
79
+ public PointQuadtree(float x, float y, float w, float h) {
80
+ this(null, x, y, w, h);
81
+ }
82
+
83
+ /**
84
+ *
85
+ * @param parent
86
+ * @param x
87
+ * @param y
88
+ * @param w
89
+ * @param h
90
+ */
91
+ public PointQuadtree(PointQuadtree parent, float x, float y, float w,
92
+ float h) {
93
+ super(x, y, w, h);
94
+ this.parent = parent;
95
+ this.type = Type.EMPTY;
96
+ mx = x + w * 0.5f;
97
+ my = y + h * 0.5f;
98
+ }
99
+
100
+ /**
101
+ *
102
+ * @param r
103
+ */
104
+ public PointQuadtree(Rect r) {
105
+ this(null, r.x, r.y, r.width, r.height);
106
+ }
107
+
108
+ private void balance() {
109
+ switch (type) {
110
+ case EMPTY:
111
+ case LEAF:
112
+ if (parent != null) {
113
+ parent.balance();
114
+ }
115
+ break;
116
+
117
+ case BRANCH:
118
+ PointQuadtree leaf = null;
119
+ if (childNW.type != Type.EMPTY) {
120
+ leaf = childNW;
121
+ }
122
+ if (childNE.type != Type.EMPTY) {
123
+ if (leaf != null) {
124
+ break;
125
+ }
126
+ leaf = childNE;
127
+ }
128
+ if (childSW.type != Type.EMPTY) {
129
+ if (leaf != null) {
130
+ break;
131
+ }
132
+ leaf = childSW;
133
+ }
134
+ if (childSE.type != Type.EMPTY) {
135
+ if (leaf != null) {
136
+ break;
137
+ }
138
+ leaf = childSE;
139
+ }
140
+ if (leaf == null) {
141
+ type = Type.EMPTY;
142
+ childNW = childNE = childSW = childSE = null;
143
+ } else if (leaf.type == Type.BRANCH) {
144
+ break;
145
+ } else {
146
+ type = Type.LEAF;
147
+ childNW = childNE = childSW = childSE = null;
148
+ value = leaf.value;
149
+ }
150
+ if (parent != null) {
151
+ parent.balance();
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ *
158
+ */
159
+ @Override
160
+ public void clear() {
161
+ childNW = childNE = childSW = childSE = null;
162
+ type = Type.EMPTY;
163
+ value = null;
164
+ }
165
+
166
+ /**
167
+ *
168
+ * @param p
169
+ * @return
170
+ */
171
+ public PointQuadtree findNode(Vec2D p) {
172
+ switch (type) {
173
+ case EMPTY:
174
+ return null;
175
+ case LEAF:
176
+ return value.x == x && value.y == y ? this : null;
177
+ case BRANCH:
178
+ return getQuadrantForPoint(p.x, p.y).findNode(p);
179
+ default:
180
+ throw new IllegalStateException("Invalid node type");
181
+ }
182
+ };
183
+
184
+ private PointQuadtree getQuadrantForPoint(float x, float y) {
185
+ if (x < mx) {
186
+ return y < my ? childNW : childSW;
187
+ } else {
188
+ return y < my ? childNE : childSE;
189
+ }
190
+ }
191
+
192
+ /**
193
+ *
194
+ * @param p
195
+ * @return
196
+ */
197
+ @Override
198
+ public boolean index(Vec2D p) {
199
+ if (containsPoint(p)) {
200
+ switch (type) {
201
+ case EMPTY:
202
+ setPoint(p);
203
+ return true;
204
+
205
+ case LEAF:
206
+ if (value.x == p.x && value.y == p.y) {
207
+ return false;
208
+ } else {
209
+ split();
210
+ return getQuadrantForPoint(p.x, p.y).index(p);
211
+ }
212
+
213
+ case BRANCH:
214
+ return getQuadrantForPoint(p.x, p.y).index(p);
215
+ }
216
+ }
217
+ return false;
218
+ }
219
+
220
+ /**
221
+ *
222
+ * @param p
223
+ * @return
224
+ */
225
+ @Override
226
+ public boolean isIndexed(Vec2D p) {
227
+ return findNode(p) != null;
228
+ }
229
+
230
+ /**
231
+ *
232
+ * @param p
233
+ * @param radius
234
+ * @param results
235
+ * @return
236
+ */
237
+ @Override
238
+ public List<Vec2D> itemsWithinRadius(Vec2D p, float radius,
239
+ List<Vec2D> results) {
240
+ if (intersectsCircle(p, radius)) {
241
+ if (type == Type.LEAF) {
242
+ if (value.distanceToSquared(p) < radius * radius) {
243
+ if (results == null) {
244
+ results = new ArrayList<>();
245
+ }
246
+ results.add(value);
247
+ }
248
+ } else if (type == Type.BRANCH) {
249
+ PointQuadtree[] children = new PointQuadtree[] {
250
+ childNW, childNE, childSW, childSE
251
+ };
252
+ for (int i = 0; i < 4; i++) {
253
+ if (children[i] != null) {
254
+ results = children[i].itemsWithinRadius(p, radius,
255
+ results);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ return results;
261
+ }
262
+
263
+ /**
264
+ *
265
+ * @param bounds
266
+ * @param results
267
+ * @return
268
+ */
269
+ public List<Vec2D> itemsWithinRect(Rect bounds, List<Vec2D> results) {
270
+ if (bounds.intersectsRect(this)) {
271
+ if (type == Type.LEAF) {
272
+ if (bounds.containsPoint(value)) {
273
+ if (results == null) {
274
+ results = new ArrayList<>();
275
+ }
276
+ results.add(value);
277
+ }
278
+ } else if (type == Type.BRANCH) {
279
+ PointQuadtree[] children = new PointQuadtree[] {
280
+ childNW, childNE, childSW, childSE
281
+ };
282
+ for (int i = 0; i < 4; i++) {
283
+ if (children[i] != null) {
284
+ results = children[i].itemsWithinRect(bounds, results);
285
+ }
286
+ }
287
+ }
288
+ }
289
+ return results;
290
+ }
291
+
292
+ /**
293
+ *
294
+ * @param visitor
295
+ */
296
+ public void prewalk(QuadtreeVisitor visitor) {
297
+ switch (type) {
298
+ case LEAF:
299
+ visitor.visitNode(this);
300
+ break;
301
+
302
+ case BRANCH:
303
+ visitor.visitNode(this);
304
+ childNW.prewalk(visitor);
305
+ childNE.prewalk(visitor);
306
+ childSW.prewalk(visitor);
307
+ childSE.prewalk(visitor);
308
+ break;
309
+ }
310
+ }
311
+
312
+ /**
313
+ *
314
+ * @param p
315
+ * @param q
316
+ * @return
317
+ */
318
+ @Override
319
+ public boolean reindex(Vec2D p, Vec2D q) {
320
+ unindex(p);
321
+ return index(q);
322
+ }
323
+
324
+ private void setPoint(Vec2D p) {
325
+ if (type == Type.BRANCH) {
326
+ throw new IllegalStateException("invalid node type: BRANCH");
327
+ }
328
+ type = Type.LEAF;
329
+ value = p;
330
+ }
331
+
332
+ /**
333
+ *
334
+ * @return
335
+ */
336
+ @Override
337
+ public int size() {
338
+ return 0;
339
+ }
340
+
341
+ private void split() {
342
+ Vec2D oldPoint = value;
343
+ value = null;
344
+
345
+ type = Type.BRANCH;
346
+
347
+ float w2 = width * 0.5f;
348
+ float h2 = height * 0.5f;
349
+
350
+ childNW = new PointQuadtree(this, x, y, w2, h2);
351
+ childNE = new PointQuadtree(this, x + w2, y, w2, h2);
352
+ childSW = new PointQuadtree(this, x, y + h2, w2, h2);
353
+ childSE = new PointQuadtree(this, x + w2, y + h2, w2, h2);
354
+
355
+ index(oldPoint);
356
+ }
357
+
358
+ /**
359
+ *
360
+ * @param p
361
+ * @return
362
+ */
363
+ @Override
364
+ public boolean unindex(Vec2D p) {
365
+ PointQuadtree node = findNode(p);
366
+ if (node != null) {
367
+ node.value = null;
368
+ node.type = Type.EMPTY;
369
+ node.balance();
370
+ return true;
371
+ } else {
372
+ return false;
373
+ }
374
+ }
375
+ }
@@ -0,0 +1,1038 @@
1
+ /*
2
+ * __ .__ .__ ._____.
3
+ * _/ |_ _______ __|__| ____ | | |__\_ |__ ______
4
+ * \ __\/ _ \ \/ / |/ ___\| | | || __ \ / ___/
5
+ * | | ( <_> > <| \ \___| |_| || \_\ \\___ \
6
+ * |__| \____/__/\_ \__|\___ >____/__||___ /____ >
7
+ * \/ \/ \/ \/
8
+ *
9
+ * Copyright (c) 2006-2011 Karsten Schmidt
10
+ *
11
+ * This library is free software; you can redistribute it and/or
12
+ * modify it under the terms of the GNU Lesser General Public
13
+ * License as published by the Free Software Foundation; either
14
+ * version 2.1 of the License, or (at your option) any later version.
15
+ *
16
+ * http://creativecommons.org/licenses/LGPL/2.1/
17
+ *
18
+ * This library is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
+ * Lesser General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU Lesser General Public
24
+ * License along with this library; if not, write to the Free Software
25
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26
+ */
27
+
28
+ package toxi.geom;
29
+
30
+ import java.util.ArrayList;
31
+ import java.util.Collections;
32
+ import java.util.Iterator;
33
+ import java.util.List;
34
+
35
+ import javax.xml.bind.annotation.XmlElement;
36
+
37
+ import toxi.geom.Line2D.LineIntersection;
38
+ import toxi.geom.Line2D.LineIntersection.Type;
39
+ import toxi.geom.mesh.Mesh3D;
40
+ import toxi.geom.mesh.TriangleMesh;
41
+ import toxi.math.MathUtils;
42
+
43
+ /**
44
+ * Container type for convex polygons. Implements {@link Shape2D}.
45
+ */
46
+ public class Polygon2D implements Shape2D, Iterable<Vec2D> {
47
+
48
+ /**
49
+ * Constructs a new regular polygon from the given base line/edge.
50
+ *
51
+ * @param baseA
52
+ * left point of the base edge
53
+ * @param baseB
54
+ * right point of the base edge
55
+ * @param res
56
+ * number of polygon vertices
57
+ * @return polygon
58
+ */
59
+ public static Polygon2D fromBaseEdge(Vec2D baseA, Vec2D baseB, int res) {
60
+ float theta = -(MathUtils.PI - (MathUtils.PI * (res - 2) / res));
61
+ Vec2D dir = baseB.sub(baseA);
62
+ Vec2D prev = baseB;
63
+ Polygon2D poly = new Polygon2D(baseA, baseB);
64
+ for (int i = 1; i < res - 1; i++) {
65
+ Vec2D p = prev.add(dir.getRotated(theta * i));
66
+ poly.add(p);
67
+ prev = p;
68
+ }
69
+ return poly;
70
+ }
71
+
72
+ /**
73
+ * Constructs a regular polygon from the given edge length and number of
74
+ * vertices. This automatically computes the radius of the circle the
75
+ * polygon is inscribed in.
76
+ *
77
+ * <p>
78
+ * More information: http://en.wikipedia.org/wiki/Regular_polygon#Radius
79
+ * </p>
80
+ *
81
+ * @param len
82
+ * desired edge length
83
+ * @param res
84
+ * number of vertices
85
+ * @return polygon
86
+ */
87
+ public static Polygon2D fromEdgeLength(float len, int res) {
88
+ return new Circle(getRadiusForEdgeLength(len, res)).toPolygon2D(res);
89
+ }
90
+
91
+ /**
92
+ * Computes the radius of the circle the regular polygon with the desired
93
+ * edge length is inscribed in
94
+ *
95
+ * @param len
96
+ * edge length
97
+ * @param res
98
+ * number of polygon vertices
99
+ * @return radius
100
+ */
101
+ public static float getRadiusForEdgeLength(float len, int res) {
102
+ return len / (2 * MathUtils.sin(MathUtils.PI / res));
103
+ }
104
+
105
+ /**
106
+ *
107
+ */
108
+ @XmlElement(name = "v")
109
+ public List<Vec2D> vertices = new ArrayList<Vec2D>();
110
+
111
+ /**
112
+ *
113
+ */
114
+ public Polygon2D() {
115
+ }
116
+
117
+ /**
118
+ *
119
+ * @param points
120
+ */
121
+ public Polygon2D(List<Vec2D> points) {
122
+ for (Vec2D p : points) {
123
+ add(p.copy());
124
+ }
125
+ }
126
+
127
+ /**
128
+ *
129
+ * @param points
130
+ */
131
+ public Polygon2D(Vec2D... points) {
132
+ for (Vec2D p : points) {
133
+ add(p.copy());
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Adds a new vertex to the polygon (builder pattern).
139
+ *
140
+ * @param x
141
+ * @param y
142
+ * @return itself
143
+ */
144
+ public Polygon2D add(float x, float y) {
145
+ return add(new Vec2D(x, y));
146
+ }
147
+
148
+ /**
149
+ * Adds a new vertex to the polygon (builder pattern).
150
+ *
151
+ * @param p
152
+ * vertex point to add
153
+ * @return itself
154
+ */
155
+ public Polygon2D add(Vec2D p) {
156
+ if (!vertices.contains(p)) {
157
+ vertices.add(p);
158
+ }
159
+ return this;
160
+ }
161
+
162
+ /**
163
+ * Centers the polygon around the world origin (0,0).
164
+ *
165
+ * @return itself
166
+ */
167
+ public Polygon2D center() {
168
+ return center(null);
169
+ }
170
+
171
+ /**
172
+ * Centers the polygon so that its new centroid is at the given point.
173
+ *
174
+ * @param origin
175
+ * new centroid or null to center around (0,0)
176
+ * @return itself
177
+ */
178
+ public Polygon2D center(ReadonlyVec2D origin) {
179
+ Vec2D centroid = getCentroid();
180
+ Vec2D delta = origin != null ? origin.sub(centroid) : centroid.invert();
181
+ for (Vec2D v : vertices) {
182
+ v.addSelf(delta);
183
+ }
184
+ return this;
185
+ }
186
+
187
+ public boolean containsPoint(ReadonlyVec2D p) {
188
+ int num = vertices.size();
189
+ int i, j = num - 1;
190
+ boolean oddNodes = false;
191
+ float px = p.x();
192
+ float py = p.y();
193
+ for (i = 0; i < num; i++) {
194
+ Vec2D vi = vertices.get(i);
195
+ Vec2D vj = vertices.get(j);
196
+ if (vi.y < py && vj.y >= py || vj.y < py && vi.y >= py) {
197
+ if (vi.x + (py - vi.y) / (vj.y - vi.y) * (vj.x - vi.x) < px) {
198
+ oddNodes = !oddNodes;
199
+ }
200
+ }
201
+ j = i;
202
+ }
203
+ return oddNodes;
204
+ }
205
+
206
+ /**
207
+ *
208
+ * @param poly
209
+ * @return
210
+ */
211
+ public boolean containsPolygon(Polygon2D poly) {
212
+ for (Vec2D p : poly.vertices) {
213
+ if (!containsPoint(p)) {
214
+ return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+
220
+ /**
221
+ *
222
+ * @return
223
+ */
224
+ public Polygon2D copy() {
225
+ return new Polygon2D(vertices);
226
+ }
227
+
228
+ /**
229
+ * Flips the ordering of the polygon's vertices.
230
+ *
231
+ * @return itself
232
+ */
233
+ public Polygon2D flipVertexOrder() {
234
+ Collections.reverse(vertices);
235
+ return this;
236
+ }
237
+
238
+ /**
239
+ * Returns the vertex at the given index. This function follows Python
240
+ * convention, in that if the index is negative, it is considered relative
241
+ * to the list end. Therefore the vertex at index -1 is the last vertex in
242
+ * the list.
243
+ *
244
+ * @param i
245
+ * index
246
+ * @return vertex
247
+ */
248
+ public Vec2D get(int i) {
249
+ if (i < 0) {
250
+ i += vertices.size();
251
+ }
252
+ return vertices.get(i);
253
+ }
254
+
255
+ /**
256
+ * Computes the length of this polygon's apothem. This will only be valid if
257
+ * the polygon is regular. More info: http://en.wikipedia.org/wiki/Apothem
258
+ *
259
+ * @return apothem length
260
+ */
261
+ public float getApothem() {
262
+ return vertices.get(0).interpolateTo(vertices.get(1), 0.5f)
263
+ .distanceTo(getCentroid());
264
+ }
265
+
266
+ /**
267
+ * Computes the area of the polygon, provided it isn't self intersecting.
268
+ * Code ported from:
269
+ * http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
270
+ *
271
+ * @return polygon area
272
+ */
273
+ public float getArea() {
274
+ float area = 0;
275
+ for (int i = 0, num = vertices.size(); i < num; i++) {
276
+ Vec2D a = vertices.get(i);
277
+ Vec2D b = vertices.get((i + 1) % num);
278
+ area += a.x * b.y;
279
+ area -= a.y * b.x;
280
+ }
281
+ area *= 0.5f;
282
+ return area;
283
+ }
284
+
285
+ public Circle getBoundingCircle() {
286
+ return Circle.newBoundingCircle(vertices);
287
+ }
288
+
289
+ /**
290
+ * Returns the polygon's bounding rect.
291
+ *
292
+ * @return bounding rect
293
+ * @see toxi.geom.Shape2D#getBounds()
294
+ */
295
+ public Rect getBounds() {
296
+ return Rect.getBoundingRect(vertices);
297
+ }
298
+
299
+ /**
300
+ * Computes the polygon's centre of mass. Code ported from:
301
+ * http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
302
+ *
303
+ * @return centroid point
304
+ */
305
+ public Vec2D getCentroid() {
306
+ Vec2D res = new Vec2D();
307
+ for (int i = 0, num = vertices.size(); i < num; i++) {
308
+ Vec2D a = vertices.get(i);
309
+ Vec2D b = vertices.get((i + 1) % num);
310
+ float crossP = a.x * b.y - b.x * a.y;
311
+ res.x += (a.x + b.x) * crossP;
312
+ res.y += (a.y + b.y) * crossP;
313
+ }
314
+ return res.scale(1f / (6 * getArea()));
315
+ }
316
+
317
+ /**
318
+ * Computes the polygon's circumference, the length of its perimeter.
319
+ *
320
+ * @return perimiter length
321
+ *
322
+ * @see toxi.geom.Shape2D#getCircumference()
323
+ */
324
+ public float getCircumference() {
325
+ float circ = 0;
326
+ for (int i = 0, num = vertices.size(); i < num; i++) {
327
+ circ += vertices.get(i).distanceTo(vertices.get((i + 1) % num));
328
+ }
329
+ return circ;
330
+ }
331
+
332
+ /**
333
+ *
334
+ * @param p
335
+ * @return
336
+ */
337
+ public Vec2D getClosestPointTo(ReadonlyVec2D p) {
338
+ float minD = Float.MAX_VALUE;
339
+ Vec2D q = null;
340
+ for (Line2D l : getEdges()) {
341
+ Vec2D c = l.closestPointTo(p);
342
+ float d = c.distanceToSquared(p);
343
+ if (d < minD) {
344
+ q = c;
345
+ minD = d;
346
+ }
347
+ }
348
+ return q;
349
+ }
350
+
351
+ /**
352
+ *
353
+ * @param p
354
+ * @return
355
+ */
356
+ public Vec2D getClosestVertexTo(ReadonlyVec2D p) {
357
+ float minD = Float.MAX_VALUE;
358
+ Vec2D q = null;
359
+ for (Vec2D v : vertices) {
360
+ float d = v.distanceToSquared(p);
361
+ if (d < minD) {
362
+ q = v;
363
+ minD = d;
364
+ }
365
+ }
366
+ return q;
367
+ }
368
+
369
+ /**
370
+ * Returns a list of {@link Line2D} segments representing the polygon edges.
371
+ *
372
+ * @return list of lines
373
+ */
374
+ public List<Line2D> getEdges() {
375
+ int num = vertices.size();
376
+ List<Line2D> edges = new ArrayList<Line2D>(num);
377
+ for (int i = 0; i < num; i++) {
378
+ edges.add(new Line2D(vertices.get(i), vertices.get((i + 1) % num)));
379
+ }
380
+ return edges;
381
+ }
382
+
383
+ /**
384
+ * @return
385
+ * @see #getNumVertices()
386
+ */
387
+ @Deprecated
388
+ public int getNumPoints() {
389
+ return getNumVertices();
390
+ }
391
+
392
+ /**
393
+ * Returns the number of polygon vertices.
394
+ *
395
+ * @return vertex count
396
+ */
397
+ public int getNumVertices() {
398
+ return vertices.size();
399
+ }
400
+
401
+ /**
402
+ * Creates a random point within the polygon. This is only guaranteed to
403
+ * work with regular polygons.
404
+ *
405
+ * @return Vec2D
406
+ */
407
+ public Vec2D getRandomPoint() {
408
+ List<Line2D> edges = getEdges();
409
+ int numEdges = edges.size();
410
+ Line2D ea = edges.get(MathUtils.random(numEdges));
411
+ Line2D eb = null;
412
+ // and another one, making sure it's different
413
+ while (eb == null || eb.equals(ea)) {
414
+ eb = edges.get(MathUtils.random(numEdges));
415
+ }
416
+ // pick a random point on edge A
417
+ Vec2D p = ea.a.interpolateTo(ea.b, MathUtils.random(1f));
418
+ // then randomly interpolate to another random point on edge B
419
+ return p.interpolateToSelf(
420
+ eb.a.interpolateTo(eb.b, MathUtils.random(1f)),
421
+ MathUtils.random(1f));
422
+ }
423
+
424
+ /**
425
+ * Repeatedly inserts vertices as mid points of the longest edges until the
426
+ * new vertex count is reached.
427
+ *
428
+ * @param count
429
+ * new vertex count
430
+ * @return itself
431
+ */
432
+ public Polygon2D increaseVertexCount(int count) {
433
+ int num = vertices.size();
434
+ while (num < count) {
435
+ // find longest edge
436
+ int longestID = 0;
437
+ float maxD = 0;
438
+ for (int i = 0; i < num; i++) {
439
+ float d = vertices.get(i).distanceToSquared(
440
+ vertices.get((i + 1) % num));
441
+ if (d > maxD) {
442
+ longestID = i;
443
+ maxD = d;
444
+ }
445
+ }
446
+ // insert mid point of longest segment in vertex list
447
+ Vec2D m = vertices.get(longestID)
448
+ .add(vertices.get((longestID + 1) % num)).scaleSelf(0.5f);
449
+ vertices.add(longestID + 1, m);
450
+ num++;
451
+ }
452
+ return this;
453
+ }
454
+
455
+ /**
456
+ *
457
+ * @param l
458
+ * @param edges
459
+ * @return
460
+ */
461
+ protected boolean intersectsLine(Line2D l, List<Line2D> edges) {
462
+ for (Line2D e : edges) {
463
+ final Type isec = l.intersectLine(e).getType();
464
+ if (isec == Type.INTERSECTING || isec == Type.COINCIDENT) {
465
+ return true;
466
+ }
467
+ }
468
+ return false;
469
+ }
470
+
471
+ /**
472
+ * Checks if the given polygon intersect this one by checking all edges for
473
+ * line intersections.
474
+ *
475
+ * @param poly
476
+ * @return true, if polygons intersect.
477
+ */
478
+ public boolean intersectsPolygon(Polygon2D poly) {
479
+ List<Line2D> edgesB = poly.getEdges();
480
+ for (Line2D ea : getEdges()) {
481
+ if (intersectsLine(ea, edgesB)) {
482
+ return true;
483
+ }
484
+ }
485
+ return false;
486
+ }
487
+
488
+ /**
489
+ *
490
+ * @param r
491
+ * @return
492
+ */
493
+ public boolean intersectsRect(Rect r) {
494
+ List<Line2D> edges = r.getEdges();
495
+ for (Line2D ea : getEdges()) {
496
+ if (intersectsLine(ea, edges)) {
497
+ return true;
498
+ }
499
+ }
500
+ return false;
501
+ }
502
+
503
+ /**
504
+ * Checks if the vertices of this polygon are in clockwise ordering by
505
+ * examining all vertices as a sequence of triangles. The test relies on the
506
+ * fact that the {@link #getArea()} method will produce negative results for
507
+ * ant-clockwise ordered polygons.
508
+ *
509
+ * @return true, if clockwise
510
+ */
511
+ public boolean isClockwise() {
512
+ return getArea() > 0;
513
+ }
514
+
515
+ /**
516
+ * Checks if the polygon is convex.
517
+ *
518
+ * @return true, if convex.
519
+ */
520
+ public boolean isConvex() {
521
+ boolean isPositive = false;
522
+ int num = vertices.size();
523
+ for (int i = 0; i < num; i++) {
524
+ int prev = (i == 0) ? num - 1 : i - 1;
525
+ int next = (i == num - 1) ? 0 : i + 1;
526
+ Vec2D d0 = vertices.get(i).sub(vertices.get(prev));
527
+ Vec2D d1 = vertices.get(next).sub(vertices.get(i));
528
+ boolean newIsP = (d0.cross(d1) > 0);
529
+ if (i == 0) {
530
+ isPositive = newIsP;
531
+ } else if (isPositive != newIsP) {
532
+ return false;
533
+ }
534
+ }
535
+ return true;
536
+ }
537
+
538
+ /**
539
+ *
540
+ * @return
541
+ */
542
+ public Iterator<Vec2D> iterator() {
543
+ return vertices.iterator();
544
+ }
545
+
546
+ /**
547
+ * Given the sequentially connected points p1, p2, p3, this function returns
548
+ * a bevel-offset replacement for point p2.
549
+ *
550
+ * Note: If vectors p1->p2 and p2->p3 are exactly 180 degrees opposed, or if
551
+ * either segment is zero then no offset will be applied.
552
+ *
553
+ * @param x1
554
+ * @param y1
555
+ * @param x2
556
+ * @param y2
557
+ * @param x3
558
+ * @param y3
559
+ * @param distance
560
+ * @param out
561
+ *
562
+ * @see http://alienryderflex.com/polygon_inset/
563
+ */
564
+ protected void offsetCorner(float x1, float y1, float x2, float y2,
565
+ float x3, float y3, float distance, Vec2D out) {
566
+
567
+ float c1 = x2, d1 = y2, c2 = x2, d2 = y2;
568
+ float dx1, dy1, dist1, dx2, dy2, dist2, insetX, insetY;
569
+
570
+ dx1 = x2 - x1;
571
+ dy1 = y2 - y1;
572
+ dist1 = (float) Math.sqrt(dx1 * dx1 + dy1 * dy1);
573
+ dx2 = x3 - x2;
574
+ dy2 = y3 - y2;
575
+ dist2 = (float) Math.sqrt(dx2 * dx2 + dy2 * dy2);
576
+
577
+ if (dist1 < MathUtils.EPS || dist2 < MathUtils.EPS) {
578
+ return;
579
+ }
580
+ dist1 = distance / dist1;
581
+ dist2 = distance / dist2;
582
+
583
+ insetX = dy1 * dist1;
584
+ insetY = -dx1 * dist1;
585
+ x1 += insetX;
586
+ c1 += insetX;
587
+ y1 += insetY;
588
+ d1 += insetY;
589
+ insetX = dy2 * dist2;
590
+ insetY = -dx2 * dist2;
591
+ x3 += insetX;
592
+ c2 += insetX;
593
+ y3 += insetY;
594
+ d2 += insetY;
595
+
596
+ if (c1 == c2 && d1 == d2) {
597
+ out.set(c1, d1);
598
+ return;
599
+ }
600
+
601
+ Line2D l1 = new Line2D(new Vec2D(x1, y1), new Vec2D(c1, d1));
602
+ Line2D l2 = new Line2D(new Vec2D(c2, d2), new Vec2D(x3, y3));
603
+ LineIntersection isec = l1.intersectLine(l2);
604
+ final Vec2D ipos = isec.getPos();
605
+ if (ipos != null) {
606
+ out.set(ipos);
607
+ }
608
+ }
609
+
610
+ /**
611
+ * Moves each line segment of the polygon in/outward perpendicular by the
612
+ * given distance. New line segments and polygon vertices are created by
613
+ * computing the intersection points of the displaced segments. Choosing an
614
+ * too large displacement amount will result in deformation/undefined
615
+ * behavior with various self intersections. Should that happen, please try
616
+ * to clean up the shape using the {@link #toOutline()} method.
617
+ *
618
+ * @param distance
619
+ * offset/inset distance (negative for inset)
620
+ * @return itself
621
+ */
622
+ public Polygon2D offsetShape(float distance) {
623
+ int num = vertices.size() - 1;
624
+ if (num > 1) {
625
+ float startX = vertices.get(0).x;
626
+ float startY = vertices.get(0).y;
627
+ float c = vertices.get(num).x;
628
+ float d = vertices.get(num).y;
629
+ float e = startX;
630
+ float f = startY;
631
+ for (int i = 0; i < num; i++) {
632
+ float a = c;
633
+ float b = d;
634
+ c = e;
635
+ d = f;
636
+ e = vertices.get(i + 1).x;
637
+ f = vertices.get(i + 1).y;
638
+ offsetCorner(a, b, c, d, e, f, distance, vertices.get(i));
639
+ }
640
+ offsetCorner(c, d, e, f, startX, startY, distance,
641
+ vertices.get(num));
642
+ }
643
+ return this;
644
+ }
645
+
646
+ /**
647
+ * Reduces the number of vertices in the polygon based on the given minimum
648
+ * edge length. Only vertices with at least this distance between them will
649
+ * be kept.
650
+ *
651
+ * @param minEdgeLen
652
+ * @return itself
653
+ */
654
+ public Polygon2D reduceVertices(float minEdgeLen) {
655
+ minEdgeLen *= minEdgeLen;
656
+ List<Vec2D> reduced = new ArrayList<Vec2D>();
657
+ Vec2D prev = vertices.get(0);
658
+ reduced.add(prev);
659
+ int num = vertices.size() - 1;
660
+ for (int i = 1; i < num; i++) {
661
+ Vec2D v = vertices.get(i);
662
+ if (prev.distanceToSquared(v) >= minEdgeLen) {
663
+ reduced.add(v);
664
+ prev = v;
665
+ }
666
+ }
667
+ if (vertices.get(0).distanceToSquared(vertices.get(num)) >= minEdgeLen) {
668
+ reduced.add(vertices.get(num));
669
+ }
670
+ vertices = reduced;
671
+ return this;
672
+ }
673
+
674
+ /**
675
+ * Removes duplicate vertices from the polygon. Only successive points are
676
+ * recognized as duplicates.
677
+ *
678
+ * @param tolerance
679
+ * snap distance for finding duplicates
680
+ * @return itself
681
+ */
682
+ public Polygon2D removeDuplicates(float tolerance) {
683
+ Vec2D prev = null;
684
+ for (Iterator<Vec2D> iv = vertices.iterator(); iv.hasNext();) {
685
+ Vec2D p = iv.next();
686
+ if (p.equalsWithTolerance(prev, tolerance)) {
687
+ iv.remove();
688
+ } else {
689
+ prev = p;
690
+ }
691
+ }
692
+ int num = vertices.size();
693
+ if (num > 0) {
694
+ Vec2D last = vertices.get(num - 1);
695
+ if (last.equalsWithTolerance(vertices.get(0), tolerance)) {
696
+ vertices.remove(last);
697
+ }
698
+ }
699
+ return this;
700
+ }
701
+
702
+ /**
703
+ *
704
+ * @param theta
705
+ * @return
706
+ */
707
+ public Polygon2D rotate(float theta) {
708
+ for (Vec2D v : vertices) {
709
+ v.rotate(theta);
710
+ }
711
+ return this;
712
+ }
713
+
714
+ /**
715
+ *
716
+ * @param scale
717
+ * @return
718
+ */
719
+ public Polygon2D scale(float scale) {
720
+ return scale(scale, scale);
721
+ }
722
+
723
+ /**
724
+ *
725
+ * @param x
726
+ * @param y
727
+ * @return
728
+ */
729
+ public Polygon2D scale(float x, float y) {
730
+ for (Vec2D v : vertices) {
731
+ v.scaleSelf(x, y);
732
+ }
733
+ return this;
734
+ }
735
+
736
+ /**
737
+ *
738
+ * @param scale
739
+ * @return
740
+ */
741
+ public Polygon2D scale(ReadonlyVec2D scale) {
742
+ return scale(scale.x(), scale.y());
743
+ }
744
+
745
+ /**
746
+ *
747
+ * @param scale
748
+ * @return
749
+ */
750
+ public Polygon2D scaleSize(float scale) {
751
+ return scaleSize(scale, scale);
752
+ }
753
+
754
+ /**
755
+ *
756
+ * @param x
757
+ * @param y
758
+ * @return
759
+ */
760
+ public Polygon2D scaleSize(float x, float y) {
761
+ Vec2D centroid = getCentroid();
762
+ for (Vec2D v : vertices) {
763
+ v.subSelf(centroid).scaleSelf(x, y).addSelf(centroid);
764
+ }
765
+ return this;
766
+ }
767
+
768
+ /**
769
+ *
770
+ * @param scale
771
+ * @return
772
+ */
773
+ public Polygon2D scaleSize(ReadonlyVec2D scale) {
774
+ return scaleSize(scale.x(), scale.y());
775
+ }
776
+
777
+ /**
778
+ * Applies a laplacian-style smooth operation to all polygon vertices,
779
+ * causing sharp corners/angles to widen and results in a general smoother
780
+ * shape. Let the current vertex be A and its neighbours P and Q, then A
781
+ * will be moved by a specified amount into the direction given by
782
+ * (P-A)+(Q-A). Additionally, and to avoid shrinking of the shape through
783
+ * repeated iteration of this procedure, the vector A - C (Polygon centroid)
784
+ * is added as counter force and a weight for its impact can be specified.
785
+ * To keep the average size of the polygon stable, this weight value should
786
+ * be ~1/2 of the smooth amount.
787
+ *
788
+ * @param amount
789
+ * smooth amount (between 0 < x < 0.5)
790
+ * @param baseWeight
791
+ * counter weight (0 <= x < 1/2 * smooth amount)
792
+ * @return itself
793
+ */
794
+ public Polygon2D smooth(float amount, float baseWeight) {
795
+ Vec2D centroid = getCentroid();
796
+ int num = vertices.size();
797
+ List<Vec2D> filtered = new ArrayList<Vec2D>(num);
798
+ for (int i = 0, j = num - 1, k = 1; i < num; i++) {
799
+ Vec2D a = vertices.get(i);
800
+ Vec2D dir = vertices.get(j).sub(a).addSelf(vertices.get(k).sub(a))
801
+ .addSelf(a.sub(centroid).scaleSelf(baseWeight));
802
+ filtered.add(a.add(dir.scaleSelf(amount)));
803
+ j++;
804
+ if (j == num) {
805
+ j = 0;
806
+ }
807
+ k++;
808
+ if (k == num) {
809
+ k = 0;
810
+ }
811
+ }
812
+ vertices.clear();
813
+ vertices.addAll(filtered);
814
+ return this;
815
+ }
816
+
817
+ /**
818
+ *
819
+ * @param mesh
820
+ * @return
821
+ */
822
+ public Mesh3D toMesh(Mesh3D mesh) {
823
+ return toMesh(mesh, null, 0);
824
+ }
825
+
826
+ /**
827
+ *
828
+ * @param mesh
829
+ * @param centroid2D
830
+ * @param extrude
831
+ * @return
832
+ */
833
+ public Mesh3D toMesh(Mesh3D mesh, Vec2D centroid2D, float extrude) {
834
+ if (mesh == null) {
835
+ mesh = new TriangleMesh();
836
+ }
837
+ final int num = vertices.size();
838
+ if (centroid2D == null) {
839
+ centroid2D = getCentroid();
840
+ }
841
+ Vec3D centroid = centroid2D.to3DXY();
842
+ centroid.z = extrude;
843
+ Rect bounds = getBounds();
844
+ Vec2D boundScale = new Vec2D(1f / bounds.width, 1f / bounds.height);
845
+ Vec2D uvC = centroid2D.sub(bounds.getTopLeft()).scaleSelf(boundScale);
846
+ for (int i = 1; i <= num; i++) {
847
+ Vec2D a = vertices.get(i % num);
848
+ Vec2D b = vertices.get(i - 1);
849
+ Vec2D uvA = a.sub(bounds.getTopLeft()).scaleSelf(boundScale);
850
+ Vec2D uvB = b.sub(bounds.getTopLeft()).scaleSelf(boundScale);
851
+ mesh.addFace(centroid, a.to3DXY(), b.to3DXY(), uvC, uvA, uvB);
852
+ }
853
+ return mesh;
854
+ }
855
+
856
+ /**
857
+ * Attempts to remove all internal self-intersections and creates a new
858
+ * polygon only consisting of perimeter vertices. Ported from:
859
+ * http://alienryderflex.com/polygon_perimeter/
860
+ *
861
+ * @return true, if process completed succcessfully.
862
+ */
863
+ public boolean toOutline() {
864
+ int corners = vertices.size();
865
+ int maxSegs = corners * 3;
866
+ List<Vec2D> newVerts = new ArrayList<Vec2D>(corners);
867
+ Vec2D[] segments = new Vec2D[maxSegs];
868
+ Vec2D[] segEnds = new Vec2D[maxSegs];
869
+ float[] segAngles = new float[maxSegs];
870
+ Vec2D start = vertices.get(0).copy();
871
+ float lastAngle = MathUtils.PI;
872
+ float a, b, c, d, e, f;
873
+ double angleDif, bestAngleDif;
874
+ int i, j = corners - 1, segs = 0;
875
+
876
+ if (corners > maxSegs) {
877
+ return false;
878
+ }
879
+
880
+ // 1,3. Reformulate the polygon as a set of line segments, and choose a
881
+ // starting point that must be on the perimeter.
882
+ for (i = 0; i < corners; i++) {
883
+ Vec2D pi = vertices.get(i);
884
+ Vec2D pj = vertices.get(j);
885
+ if (!pi.equals(pj)) {
886
+ segments[segs] = pi;
887
+ segEnds[segs++] = pj;
888
+ }
889
+ j = i;
890
+ if (pi.y > start.y || (pi.y == start.y && pi.x < start.x)) {
891
+ start.set(pi);
892
+ }
893
+ }
894
+ if (segs == 0) {
895
+ return false;
896
+ }
897
+
898
+ // 2. Break the segments up at their intersection points.
899
+ for (i = 0; i < segs - 1; i++) {
900
+ for (j = i + 1; j < segs; j++) {
901
+ Line2D li = new Line2D(segments[i], segEnds[i]);
902
+ Line2D lj = new Line2D(segments[j], segEnds[j]);
903
+ LineIntersection isec = li.intersectLine(lj);
904
+ if (isec.getType() == Type.INTERSECTING) {
905
+ Vec2D ipos = isec.getPos();
906
+ if (!ipos.equals(segments[i]) && !ipos.equals(segEnds[i])) {
907
+ if (segs == maxSegs) {
908
+ return false;
909
+ }
910
+ segments[segs] = segments[i].copy();
911
+ segEnds[segs++] = ipos.copy();
912
+ segments[i] = ipos.copy();
913
+ }
914
+ if (!ipos.equals(segments[j]) && !ipos.equals(segEnds[j])) {
915
+ if (segs == maxSegs) {
916
+ return false;
917
+ }
918
+ segments[segs] = segments[j].copy();
919
+ segEnds[segs++] = ipos.copy();
920
+ segments[j] = ipos.copy();
921
+ }
922
+ }
923
+ }
924
+ }
925
+
926
+ // Calculate the angle of each segment.
927
+ for (i = 0; i < segs; i++) {
928
+ segAngles[i] = segEnds[i].sub(segments[i]).positiveHeading();
929
+ }
930
+
931
+ // 4. Build the perimeter polygon.
932
+ c = start.x;
933
+ d = start.y;
934
+ a = c - 1;
935
+ b = d;
936
+ e = 0;
937
+ f = 0;
938
+ newVerts.add(new Vec2D(c, d));
939
+ corners = 1;
940
+ while (true) {
941
+ bestAngleDif = MathUtils.TWO_PI;
942
+ for (i = 0; i < segs; i++) {
943
+ if (segments[i].x == c && segments[i].y == d
944
+ && (segEnds[i].x != a || segEnds[i].y != b)) {
945
+ angleDif = lastAngle - segAngles[i];
946
+ while (angleDif >= MathUtils.TWO_PI) {
947
+ angleDif -= MathUtils.TWO_PI;
948
+ }
949
+ while (angleDif < 0) {
950
+ angleDif += MathUtils.TWO_PI;
951
+ }
952
+ if (angleDif < bestAngleDif) {
953
+ bestAngleDif = angleDif;
954
+ e = segEnds[i].x;
955
+ f = segEnds[i].y;
956
+ }
957
+ }
958
+ if (segEnds[i].x == c && segEnds[i].y == d
959
+ && (segments[i].x != a || segments[i].y != b)) {
960
+ angleDif = lastAngle - segAngles[i] + MathUtils.PI;
961
+ while (angleDif >= MathUtils.TWO_PI) {
962
+ angleDif -= MathUtils.TWO_PI;
963
+ }
964
+ while (angleDif < 0) {
965
+ angleDif += MathUtils.TWO_PI;
966
+ }
967
+ if (angleDif < bestAngleDif) {
968
+ bestAngleDif = angleDif;
969
+ e = segments[i].x;
970
+ f = segments[i].y;
971
+ }
972
+ }
973
+ }
974
+ if (corners > 1 && c == newVerts.get(0).x && d == newVerts.get(0).y
975
+ && e == newVerts.get(1).x && f == newVerts.get(1).y) {
976
+ corners--;
977
+ vertices = newVerts;
978
+ return true;
979
+ }
980
+ if (bestAngleDif == MathUtils.TWO_PI || corners == maxSegs) {
981
+ return false;
982
+ }
983
+ lastAngle -= bestAngleDif + MathUtils.PI;
984
+ newVerts.add(new Vec2D(e, f));
985
+ corners++;
986
+ a = c;
987
+ b = d;
988
+ c = e;
989
+ d = f;
990
+ }
991
+ }
992
+
993
+ /**
994
+ * Only needed for {@link Shape2D} interface. Returns itself.
995
+ *
996
+ * @return itself
997
+ */
998
+ public Polygon2D toPolygon2D() {
999
+ return this;
1000
+ }
1001
+
1002
+ /**
1003
+ *
1004
+ * @return
1005
+ */
1006
+ public String toString() {
1007
+ StringBuilder buf = new StringBuilder();
1008
+ for (Iterator<Vec2D> i = vertices.iterator(); i.hasNext();) {
1009
+ buf.append(i.next().toString());
1010
+ if (i.hasNext()) {
1011
+ buf.append(", ");
1012
+ }
1013
+ }
1014
+ return buf.toString();
1015
+ }
1016
+
1017
+ /**
1018
+ *
1019
+ * @param x
1020
+ * @param y
1021
+ * @return
1022
+ */
1023
+ public Polygon2D translate(float x, float y) {
1024
+ for (Vec2D v : vertices) {
1025
+ v.addSelf(x, y);
1026
+ }
1027
+ return this;
1028
+ }
1029
+
1030
+ /**
1031
+ *
1032
+ * @param offset
1033
+ * @return
1034
+ */
1035
+ public Polygon2D translate(ReadonlyVec2D offset) {
1036
+ return translate(offset.x(), offset.y());
1037
+ }
1038
+ }