toxiclibs 0.2-java → 0.5.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }