├── .gitignore
├── Scenes
├── Materials
│ ├── eppz! Geometry Star.png
│ ├── eppz! Geometry Winding.png
│ ├── eppz! Geometry Star.mat.meta
│ ├── eppz! Geometry Solid color.mat.meta
│ ├── eppz! Geometry Star.svg.meta
│ ├── eppz! Geometry Solid color.shader
│ ├── eppz! Geometry Solid color.shader.meta
│ ├── eppz! Geometry Vertex color.shader.meta
│ ├── eppz! Geometry Winding.mat.meta
│ ├── eppz! Geometry Vertex color.mat.meta
│ ├── eppz! Geometry Star.mat
│ ├── eppz! Geometry Winding.mat
│ ├── eppz! Geometry Solid color.mat
│ ├── eppz! Geometry Vertex color.mat
│ ├── eppz! Geometry Vertex color.shader
│ ├── eppz! Geometry Star.png.meta
│ ├── eppz! Geometry Winding.png.meta
│ └── eppz! Geometry Star.svg
├── 0. Polygon-point containment.unity.meta
├── Controllers.meta
├── Materials.meta
├── README.md.meta
├── 6. Vertex facing.unity.meta
├── 9. Polygon offset.unity.meta
├── 1. Polygon-Segment intersection.unity.meta
├── 10. Multiple polygon centroid.unity.meta
├── 11. Polygon triangulation (1).unity.meta
├── 11. Polygon triangulation (2).unity.meta
├── 4. Polygon-Segment containment.unity.meta
├── 7. Polygon area, Polygon winding.unity.meta
├── 5. Polygon-Polygon containment (1).unity.meta
├── 5. Polygon-Polygon containment (2).unity.meta
├── 8. Segment-Segment intersection point.unity.meta
├── Animations.meta
├── 2. Polygon permiter-Point containment (Precise).unity.meta
├── 3. Polygon permiter-Point containment (Default).unity.meta
├── Animations
│ ├── eppz! Geometry Drift.anim.meta
│ ├── eppz! Geometry Spin.anim.meta
│ └── eppz! Geometry Drift.anim
├── Controllers
│ ├── Controller_0.cs.meta
│ ├── Controller_1.cs.meta
│ ├── Controller_2.cs.meta
│ ├── Controller_3.cs.meta
│ ├── Controller_4.cs.meta
│ ├── Controller_5.cs.meta
│ ├── Controller_6.cs.meta
│ ├── Controller_8.cs.meta
│ ├── Controller_9.cs.meta
│ ├── Controller_10.cs.meta
│ ├── Controller_10.cs
│ ├── Controller_9.cs
│ ├── Controller_3.cs
│ ├── Controller_2.cs
│ ├── Controller_0.cs
│ ├── Controller_1.cs
│ ├── Controller_8.cs
│ ├── Controller_4.cs
│ ├── Controller_6.cs
│ └── Controller_5.cs
└── README.md
├── LICENSE.md.meta
├── README.md.meta
├── CHANGELOG.md.meta
├── .gitmodules
├── Lines.meta
├── Model.meta
├── AddOns.meta
├── Clipper.meta
├── Editor.meta
├── Extensions.meta
├── Inspector.meta
├── Scenes.meta
├── Source.meta
├── Triangle.NET.meta
├── Inspector
├── Editor.meta
├── PolygonInspector.cs.meta
├── Editor
│ ├── PolygonInspector.cs.meta
│ └── PolygonInspector.cs
└── PolygonInspector.cs
├── Geometry.cs.meta
├── Model
├── Edge.cs.meta
├── Polygon.cs.meta
├── Segment.cs.meta
├── Vertex.cs.meta
├── Edge.cs
├── Vertex.cs
├── Segment.cs
└── Polygon.cs
├── Source
├── Mesh.cs.meta
├── Points.cs.meta
├── Polygon.cs.meta
├── Segment.cs.meta
├── Points.cs
├── Segment.cs
├── Mesh.cs
└── Polygon.cs
├── Editor
├── Define.cs.meta
└── Define.cs
├── AddOns
├── ClipperAddOns.cs.meta
├── TriangleNetAddOns.cs.meta
├── UnityEngineAddOns.cs.meta
├── ClipperAddOns.cs
├── TriangleNetAddOns.cs
└── UnityEngineAddOns.cs
├── Extensions
├── Vector2.cs.meta
├── Vector3.cs.meta
├── Vector3.cs
└── Vector2.cs
├── Lines
├── CornerLineRenderer.cs.meta
├── GeometryLineRenderer.cs.meta
├── PolygonLineRenderer.cs.meta
├── SegmentLineRenderer.cs.meta
├── ExtendedPolygonLineRenderer.cs.meta
├── CornerLineRenderer.cs
├── SegmentLineRenderer.cs
├── PolygonLineRenderer.cs
├── ExtendedPolygonLineRenderer.cs
└── GeometryLineRenderer.cs
├── LICENSE.md
├── CHANGELOG.md
├── Geometry.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Ignore meta (OSX)
2 | .DS_Store
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Geri-Borbas/Unity.Library.eppz.Geometry/HEAD/Scenes/Materials/eppz! Geometry Star.png
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Winding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Geri-Borbas/Unity.Library.eppz.Geometry/HEAD/Scenes/Materials/eppz! Geometry Winding.png
--------------------------------------------------------------------------------
/Scenes/0. Polygon-point containment.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e02b7c9085e204e069ae845f325553bd
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Scenes/Controllers.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f08989fac9016469caf3821a1d940500
3 | folderAsset: yes
4 | DefaultImporter:
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Scenes/Materials.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 080c1a8210ced48ac92f18d29ea5a884
3 | folderAsset: yes
4 | DefaultImporter:
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/LICENSE.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 06d2f746cf4e440a29cfee71b4a267fd
3 | timeCreated: 1497714734
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 069d45a9676e948c4b1146cc9bccc4a6
3 | timeCreated: 1497713744
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7bc712b87c3914c40a77a0de88362bef
3 | timeCreated: 1497714734
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 570c8868b089a46129e63e831d69c64d
3 | timeCreated: 1497911901
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5982048bedd05448ea6ebc18c9756e26
3 | NativeFormatImporter:
4 | mainObjectFileID: -1
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Scenes/6. Vertex facing.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d666d571743524056864e011c8f55eca
3 | timeCreated: 1498050921
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/9. Polygon offset.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7e93876e5145a464d95a3e5d2118c6e1
3 | timeCreated: 1498092868
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Solid color.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7c061e9fd66494953b8c6f5e8551732f
3 | NativeFormatImporter:
4 | mainObjectFileID: -1
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Clipper"]
2 | path = Clipper
3 | url = https://github.com/eppz/Clipper
4 | branch = Release
5 | [submodule "Triangle.NET"]
6 | path = Triangle.NET
7 | url = https://github.com/eppz/Triangle.NET
8 | branch = Release
9 |
--------------------------------------------------------------------------------
/Lines.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: aac3609318e6245b085144952c707182
3 | folderAsset: yes
4 | timeCreated: 1497913169
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Model.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f16e57316bac740f6b1e7f515f82111b
3 | folderAsset: yes
4 | timeCreated: 1497897220
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/AddOns.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1cd35a4304cc444118c93b824de3044d
3 | folderAsset: yes
4 | timeCreated: 1497897220
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Clipper.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 08b837d20ea514f5a9f147319de87281
3 | folderAsset: yes
4 | timeCreated: 1497718686
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6ff1fe5e7ef3e466ba1a2ca31287054b
3 | folderAsset: yes
4 | timeCreated: 1497896207
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Extensions.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c0e9b58bb7ce348caab337b9b386c633
3 | folderAsset: yes
4 | timeCreated: 1497896101
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Inspector.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e62a78f31a6fa425eb220d22450f9377
3 | folderAsset: yes
4 | timeCreated: 1498154815
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ba2cc6c3c72734587b55513faba0275d
3 | folderAsset: yes
4 | timeCreated: 1497911901
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.svg.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e36a479e39783471e97138414b7a3830
3 | timeCreated: 1498005035
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Source.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0995988883c5f450daad1deb59214d31
3 | folderAsset: yes
4 | timeCreated: 1497897326
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/1. Polygon-Segment intersection.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f926ca1c66e9b4be9a8848d793a7554e
3 | timeCreated: 1498002429
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/10. Multiple polygon centroid.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6e32cb6f5418040009a33168be2f0978
3 | timeCreated: 1498094770
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/11. Polygon triangulation (1).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c9eb6241793848bcb16704dfbdc2746
3 | timeCreated: 1498151656
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/11. Polygon triangulation (2).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f65207aae8b8e4ed8b0793b9281ceed1
3 | timeCreated: 1498263534
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/4. Polygon-Segment containment.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9be22de292def42a89a3428b8d6a1de4
3 | timeCreated: 1498007156
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/7. Polygon area, Polygon winding.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b3875e1adb8e04c4d99f1af1ad2398ac
3 | timeCreated: 1498053405
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Triangle.NET.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 740dfcbf418ec42dfb19dd33879c406a
3 | folderAsset: yes
4 | timeCreated: 1497718686
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Inspector/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f8f2dcc0c620840539ee6d7deac48d40
3 | folderAsset: yes
4 | timeCreated: 1498154874
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/5. Polygon-Polygon containment (1).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3b6ad0b2719ea446ea5cb62b685306c3
3 | timeCreated: 1498014118
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/5. Polygon-Polygon containment (2).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c58e2d7e6b4b437d8a93d933c07de4e
3 | timeCreated: 1498014137
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/8. Segment-Segment intersection point.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a36f809f659b041b581eb9b62a096bc8
3 | timeCreated: 1498083392
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/Animations.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d340b255fb2824c6c808ed07190e3ecf
3 | folderAsset: yes
4 | timeCreated: 1498005378
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Solid color.shader:
--------------------------------------------------------------------------------
1 | Shader "eppz!/Geometry/Solid color"
2 | {
3 | Properties
4 | {
5 | _Color ("Color", Color) = (1,1,1)
6 | }
7 |
8 | SubShader
9 | {
10 | Color [_Color]
11 | Pass {}
12 | }
13 | }
--------------------------------------------------------------------------------
/Scenes/2. Polygon permiter-Point containment (Precise).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d7885f0dcad942b7b8da07ce763aaac
3 | timeCreated: 1498004298
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Scenes/3. Polygon permiter-Point containment (Default).unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d945816aa19e84ff18b514562f0ed1fe
3 | timeCreated: 1498012570
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Geometry.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 878b0d44b0b284ac0ab5bc2a5198a424
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Model/Edge.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f8f04e7f419e0481e89a4855c1afe48d
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Model/Polygon.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3024a1cbde06044dcafead4cd24f3951
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Model/Segment.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 578ca8bb78e354a369b7aa397c854195
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Model/Vertex.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bb3b0c75aa3b7408dab5053d6c9a7c70
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Scenes/Animations/eppz! Geometry Drift.anim.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 18641437c1b9842b88b3cc0ece6343b4
3 | timeCreated: 1498270794
4 | licenseType: Free
5 | NativeFormatImporter:
6 | mainObjectFileID: -1
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Animations/eppz! Geometry Spin.anim.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d15258d94e7e04b69a168a2ea7249441
3 | timeCreated: 1498005102
4 | licenseType: Free
5 | NativeFormatImporter:
6 | mainObjectFileID: -1
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Solid color.shader.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 624e7bb379bc34ba2a33f5466bf22177
3 | timeCreated: 1497914795
4 | licenseType: Free
5 | ShaderImporter:
6 | defaultTextures: []
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Vertex color.shader.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 648320c5e6aa44cae8e41e668725a60f
3 | timeCreated: 1498156354
4 | licenseType: Free
5 | ShaderImporter:
6 | defaultTextures: []
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Winding.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 489fe84c7d27343df8ab8e6466d2a963
3 | timeCreated: 1498012570
4 | licenseType: Free
5 | NativeFormatImporter:
6 | mainObjectFileID: -1
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Vertex color.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 026668cf8595a4ba98235aeba073174b
3 | timeCreated: 1498156354
4 | licenseType: Free
5 | NativeFormatImporter:
6 | mainObjectFileID: -1
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Source/Mesh.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 860e2ec07f219485599d0781d0dd85f5
3 | timeCreated: 1498168825
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Editor/Define.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0262ffd8508fa49458efb1e8dcca8e85
3 | timeCreated: 1497795889
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Source/Points.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dab07af4868cd4c1d93d8606f38ccc73
3 | timeCreated: 1498268155
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Source/Polygon.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ba7a569d9f84344fd8f559eacf1ceb8b
3 | timeCreated: 1497897326
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Source/Segment.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: da61256570a8c4e098ba98d18e3728d9
3 | timeCreated: 1497897326
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/AddOns/ClipperAddOns.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6803417002d2a4b9c8db703bac12f6ec
3 | timeCreated: 1498134866
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Extensions/Vector2.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 82101dd1a6fa5449ba20dfecd0484231
3 | timeCreated: 1497896101
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Extensions/Vector3.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 39707300bf96649e9a562b8928486e25
3 | timeCreated: 1497896101
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/AddOns/TriangleNetAddOns.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4e1cfae3ee4014ce48283dc0231497e4
3 | timeCreated: 1498140463
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/AddOns/UnityEngineAddOns.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b133bb002ab4a4f95a451607be3b517e
3 | timeCreated: 1498140464
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Inspector/PolygonInspector.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a04c8437858394175bf2df9d59dc216e
3 | timeCreated: 1497897326
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Lines/CornerLineRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4b8e8313fc9274e84bd1bc1be293263c
3 | timeCreated: 1474121880
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 1100
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Lines/GeometryLineRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cab55df2272dc47bb9a91830c38acfbf
3 | timeCreated: 1474121879
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 1100
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Lines/PolygonLineRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0b0de8b2d921d454fb29a849a0e578ad
3 | timeCreated: 1474121879
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 1100
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Lines/SegmentLineRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8688db05fd6164131917f90631dc7e52
3 | timeCreated: 1474121881
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 1100
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_0.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19df9899f9375406dbc2f7e6021a5552
3 | timeCreated: 1497913130
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_1.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 037d000350edf4451ad8e72279aab154
3 | timeCreated: 1498002457
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_2.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 775f7021c685b4387b9058026247cfa9
3 | timeCreated: 1498004299
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_3.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 37357bc0d70d64e1c901063e480484c8
3 | timeCreated: 1498006461
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_4.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 539c44952ae854db1ab253813e36257a
3 | timeCreated: 1498007557
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_5.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7728c220505db4cf4bf7617872e1a3c2
3 | timeCreated: 1498014125
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_6.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5fd993e5dbca24239af8c7c0bd59dc40
3 | timeCreated: 1498050916
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_8.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c98aad19b017941b6baf0e5681732e1b
3 | timeCreated: 1498083402
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_9.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e27d5917dbd284404b61ad95207c5151
3 | timeCreated: 1498092869
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Inspector/Editor/PolygonInspector.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73ccd8c1ccf0e4694a872bc8925d6c61
3 | timeCreated: 1497898474
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Lines/ExtendedPolygonLineRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac9e1ffc88486455ea813df2ab160865
3 | timeCreated: 1498093951
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 1100
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_10.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fc0b24ddec557433d9c1fc10ea772953
3 | timeCreated: 1498094781
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: eppz! Geometry Star
10 | m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
11 | m_ShaderKeywords:
12 | m_LightmapFlags: 5
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _MainTex:
22 | m_Texture: {fileID: 2800000, guid: 643497948b6324a888e28fc3cd1cb964, type: 3}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | m_Floats: []
26 | m_Colors:
27 | - _Color: {r: 1, g: 1, b: 1, a: 1}
28 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Winding.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: eppz! Geometry Winding
10 | m_Shader: {fileID: 30, guid: 0000000000000000f000000000000000, type: 0}
11 | m_ShaderKeywords:
12 | m_LightmapFlags: 5
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _MainTex:
22 | m_Texture: {fileID: 2800000, guid: 9d715ae3a587948808be900f38d3d902, type: 3}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | m_Floats: []
26 | m_Colors:
27 | - _Color: {r: 1, g: 1, b: 1, a: 1}
28 |
--------------------------------------------------------------------------------
/Source/Points.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 |
6 | namespace EPPZ.Geometry.Source
7 | {
8 |
9 |
10 | ///
11 | /// Utility component to create point transforms from mesh vertices
12 | /// suitable to feed data into `Source.Polygon.points` component.
13 | ///
14 | [ExecuteInEditMode]
15 | public class Points : MonoBehaviour
16 | {
17 |
18 |
19 | public float scale = 0.1f;
20 |
21 |
22 | [ContextMenu("Create")]
23 | void Create()
24 | {
25 | int index = 1;
26 | foreach (Vector3 eachVertex in GetComponent().mesh.vertices)
27 | {
28 | GameObject point = GameObject.CreatePrimitive(PrimitiveType.Sphere);
29 | point.transform.parent = transform;
30 | point.transform.localPosition = eachVertex;
31 | point.transform.localScale = Vector3.one * scale;
32 | point.name = "Point "+index.ToString("00");
33 | index++;
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Geri Borbás
4 | https://twitter.com/_eppz
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Solid color.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: eppz! Geometry Solid color
10 | m_Shader: {fileID: 4800000, guid: 624e7bb379bc34ba2a33f5466bf22177, type: 3}
11 | m_ShaderKeywords:
12 | m_LightmapFlags: 5
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _BumpMap:
22 | m_Texture: {fileID: 0}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | - _MainTex:
26 | m_Texture: {fileID: 0}
27 | m_Scale: {x: 1, y: 1}
28 | m_Offset: {x: 0, y: 0}
29 | - _ParallaxMap:
30 | m_Texture: {fileID: 0}
31 | m_Scale: {x: 1, y: 1}
32 | m_Offset: {x: 0, y: 0}
33 | m_Floats:
34 | - _Parallax: 0.02
35 | - _Shininess: 0.01
36 | m_Colors:
37 | - _Color: {r: 0.9843137, g: 0.9843137, b: 0.44313726, a: 1}
38 | - _Emission: {r: 0, g: 0, b: 0, a: 0}
39 | - _SpecColor: {r: 1, g: 1, b: 1, a: 1}
40 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Vertex color.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: eppz! Geometry Vertex color
10 | m_Shader: {fileID: 4800000, guid: 648320c5e6aa44cae8e41e668725a60f, type: 3}
11 | m_ShaderKeywords:
12 | m_LightmapFlags: 5
13 | m_EnableInstancingVariants: 0
14 | m_DoubleSidedGI: 0
15 | m_CustomRenderQueue: -1
16 | stringTagMap: {}
17 | disabledShaderPasses: []
18 | m_SavedProperties:
19 | serializedVersion: 3
20 | m_TexEnvs:
21 | - _BumpMap:
22 | m_Texture: {fileID: 0}
23 | m_Scale: {x: 1, y: 1}
24 | m_Offset: {x: 0, y: 0}
25 | - _MainTex:
26 | m_Texture: {fileID: 0}
27 | m_Scale: {x: 1, y: 1}
28 | m_Offset: {x: 0, y: 0}
29 | - _ParallaxMap:
30 | m_Texture: {fileID: 0}
31 | m_Scale: {x: 1, y: 1}
32 | m_Offset: {x: 0, y: 0}
33 | m_Floats:
34 | - _Parallax: 0.02
35 | - _Shininess: 0.01
36 | m_Colors:
37 | - _Color: {r: 0.9843137, g: 0.9843137, b: 0.44313726, a: 1}
38 | - _Emission: {r: 0, g: 0, b: 0, a: 0}
39 | - _SpecColor: {r: 1, g: 1, b: 1, a: 1}
40 |
--------------------------------------------------------------------------------
/Inspector/PolygonInspector.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Inspector
13 | {
14 |
15 |
16 | public class PolygonInspector : MonoBehaviour
17 | {
18 |
19 |
20 | public Model.Polygon polygon;
21 | public int currentEdgeIndex = 0;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Vertex color.shader:
--------------------------------------------------------------------------------
1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
2 |
3 | Shader "eppz!/Geometry/Vertex color"
4 | {
5 |
6 | Properties
7 | { }
8 |
9 |
10 | SubShader
11 | {
12 |
13 |
14 | Tags {"Queue" = "Transparent"}
15 | Pass
16 | {
17 |
18 |
19 | Cull Off
20 | Lighting Off
21 | ZWrite Off
22 | ZTest Always
23 | Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
24 |
25 |
26 | CGPROGRAM
27 |
28 | #pragma vertex vert
29 | #pragma fragment frag
30 | #pragma fragmentoption ARB_precision_hint_fastest
31 | #include "UnityCG.cginc"
32 |
33 |
34 | struct vertexInput
35 | {
36 | float4 vertex : POSITION;
37 | float4 color : COLOR;
38 | float4 texcoord : TEXCOORD0;
39 | };
40 |
41 | struct vertexOutput
42 | {
43 | float4 position : SV_POSITION;
44 | float4 color : COLOR; // Vertex color
45 | float2 uv : TEXCOORD0;
46 | };
47 |
48 |
49 | vertexOutput vert (vertexInput input)
50 | {
51 | vertexOutput output;
52 |
53 | // Usual projection stuff.
54 | output.position = UnityObjectToClipPos(input.vertex);
55 | output.color = input.color;
56 | output.uv = input.texcoord;
57 |
58 | return output;
59 | }
60 |
61 | half4 frag (vertexOutput input) : COLOR
62 | {
63 | // Color (vertex).
64 | half4 output = input.color;
65 | return output;
66 | }
67 |
68 |
69 | ENDCG
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/Lines/CornerLineRenderer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | #if EPPZ_LINES
9 | using UnityEngine;
10 | using System.Collections;
11 |
12 |
13 | namespace EPPZ.Geometry.Lines
14 | {
15 |
16 |
17 | using Model;
18 |
19 |
20 | public class CornerLineRenderer : GeometryLineRenderer
21 | {
22 |
23 |
24 | public Color segmentAColor;
25 | public Color segmentBColor;
26 | public Color segmentNormalColor;
27 |
28 | public Segment segmentA;
29 | public Segment segmentB;
30 | public Segment normal;
31 |
32 |
33 | protected override void OnDraw()
34 | {
35 | DrawSegment(segmentA, segmentAColor);
36 | DrawSegment(segmentB, segmentBColor);
37 | DrawSegment(normal, segmentNormalColor);
38 | }
39 | }
40 | }
41 | #endif
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_10.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections.Generic;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Model;
17 | using Lines;
18 |
19 |
20 | ///
21 | /// 10. Multiple polygon centroid
22 | ///
23 | public class Controller_10 : MonoBehaviour
24 | {
25 |
26 | public Transform centroid;
27 | public Source.Polygon[] polygonSources;
28 | List polygons = new List();
29 |
30 |
31 | void Update()
32 | {
33 | // Collect polygons.
34 | polygons.Clear();
35 | foreach (Source.Polygon eachPolygonSource in polygonSources)
36 | { polygons.Add(eachPolygonSource.polygon); }
37 |
38 | // Calculate compund centroid.
39 | centroid.position = Geometry.CentroidOfPolygons(polygons.ToArray());
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Editor/Define.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using UnityEngine;
10 | using UnityEditor;
11 |
12 |
13 | namespace EPPZ.Geometry.Editor
14 | {
15 |
16 |
17 | [InitializeOnLoad]
18 | public class Define
19 | {
20 |
21 |
22 | const string define = "EPPZ_GEOMETRY";
23 |
24 |
25 | static Define()
26 | { AddDefineIfNeeded(); }
27 |
28 | static void AddDefineIfNeeded()
29 | {
30 | BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
31 | string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
32 | if (defines.Contains(define)) return; // Change only if needed
33 | PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, (defines + ";" + define));
34 | Debug.LogWarning(""+define+" added to Scripting Define Symbols for selected build target ("+EditorUserBuildSettings.activeBuildTarget.ToString()+").");
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Extensions/Vector3.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using UnityEngine;
10 |
11 |
12 | namespace EPPZ.Geometry
13 | {
14 |
15 |
16 | public static class Vector3_Extensions
17 | {
18 |
19 |
20 | public static Vector2 xy(this Vector3 this_)
21 | {
22 | return new UnityEngine.Vector2( this_.x, this_.y);
23 | }
24 |
25 | public static Vector2 xz(this Vector3 this_)
26 | {
27 | return new UnityEngine.Vector2( this_.x, this_.z);
28 | }
29 |
30 | public static Vector2 yz(this Vector3 this_)
31 | {
32 | return new UnityEngine.Vector2( this_.y, this_.z);
33 | }
34 |
35 | public static Vector2 yx(this Vector3 this_)
36 | {
37 | return new UnityEngine.Vector2( this_.y, this_.x);
38 | }
39 |
40 | public static Vector2 zx(this Vector3 this_)
41 | {
42 | return new UnityEngine.Vector2( this_.z, this_.x);
43 | }
44 |
45 | public static Vector2 zy(this Vector3 this_)
46 | {
47 | return new UnityEngine.Vector2( this_.z, this_.y);
48 | }
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/Source/Segment.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Source
13 | {
14 |
15 |
16 | using Model;
17 |
18 |
19 | public class Segment : MonoBehaviour
20 | {
21 |
22 |
23 | [UnityEngine.Serialization.FormerlySerializedAs("pointTransforms")]
24 | public Transform[] points;
25 |
26 | public enum UpdateMode { Awake, Update, LateUpdate };
27 | public UpdateMode update = UpdateMode.Awake;
28 |
29 | public enum Coordinates { World, Local }
30 | public Coordinates coordinates = Coordinates.World;
31 |
32 | public Model.Segment segment;
33 |
34 |
35 | void Awake()
36 | {
37 | segment = Model.Segment.SegmentWithSource(this);
38 | }
39 |
40 | void Update()
41 | {
42 | if (update == UpdateMode.Update)
43 | { UpdateModel(); }
44 | }
45 |
46 | void LateUpdate()
47 | {
48 | if (update == UpdateMode.LateUpdate)
49 | { UpdateModel(); }
50 | }
51 |
52 | void UpdateModel()
53 | {
54 | segment.UpdateWithSource(this);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Lines/SegmentLineRenderer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | #if EPPZ_LINES
9 | using UnityEngine;
10 | using System.Collections;
11 |
12 |
13 | namespace EPPZ.Geometry.Lines
14 | {
15 |
16 |
17 | using EPPZ.Lines;
18 | using Model;
19 |
20 |
21 | public class SegmentLineRenderer : GeometryLineRenderer
22 | {
23 |
24 |
25 | public Color lineColor;
26 | public Color boundsColor;
27 | public bool normals = false;
28 |
29 | Segment segment;
30 | Source.Segment segmentSource;
31 |
32 | void Start()
33 | {
34 | // Model reference.
35 | segmentSource = GetComponent();
36 | segment = segmentSource.segment;
37 | }
38 |
39 | protected override void OnDraw()
40 | {
41 | if (segmentSource.coordinates == Source.Segment.Coordinates.World)
42 | {
43 | DrawRect(segment.bounds, boundsColor);
44 | DrawSegment(segment, lineColor, normals);
45 | }
46 | else
47 | {
48 | DrawRectWithTransform(segment.bounds, boundsColor, this.transform);
49 | DrawSegmentWithTransform(segment, lineColor, this.transform, normals);
50 | }
51 | }
52 | }
53 | }
54 | #endif
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_9.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 | using Inspector;
19 |
20 |
21 | ///
22 | /// 9. Polygon offset
23 | ///
24 | public class Controller_9 : MonoBehaviour
25 | {
26 |
27 |
28 | [Range(0,2)] public float offset = 0.2f;
29 |
30 | public Source.Polygon polygonSource;
31 | public PolygonLineRenderer offsetPolygonRenderer;
32 |
33 | private Polygon offsetPolygon;
34 | private Polygon polygon { get { return polygonSource.polygon; } }
35 |
36 | public PolygonInspector polygonInspector;
37 | public PolygonInspector offsetPolygonInspector;
38 |
39 |
40 | void Start()
41 | {
42 | // Debug.
43 | polygonInspector.polygon = polygonSource.polygon;
44 | }
45 |
46 | void Update()
47 | {
48 | offsetPolygon = polygon.OffsetPolygon(offset);
49 |
50 | // Render.
51 | offsetPolygonRenderer.polygon = offsetPolygon;
52 |
53 | // Debug.
54 | offsetPolygonInspector.polygon = offsetPolygon;
55 | }
56 | }
57 | }
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_3.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 3. Polygon permiter-Point containment (Default)
22 | ///
23 | public class Controller_3 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public Source.Polygon polygonSource;
31 | public GameObject pointSource;
32 | public PolygonLineRenderer polygonRenderer;
33 |
34 | private Polygon polygon { get { return polygonSource.polygon; } }
35 | private Vector2 point { get { return pointSource.transform.position.xy(); } }
36 |
37 |
38 | void Update()
39 | { RenderTestResult(PointContainmentTest()); }
40 |
41 | bool PointContainmentTest()
42 | {
43 | float accuracy = 0.1f;
44 | return polygon.PermiterContainsPoint(point, accuracy);
45 | }
46 |
47 | void RenderTestResult(bool testResult)
48 | {
49 | Color color = (testResult) ? passingColor : defaultColor;
50 |
51 | // Layout colors.
52 | polygonRenderer.lineColor = color;
53 | pointSource.GetComponent().material.color = color;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/Lines/PolygonLineRenderer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | #if EPPZ_LINES
9 | using UnityEngine;
10 | using System.Collections;
11 |
12 |
13 | namespace EPPZ.Geometry.Lines
14 | {
15 |
16 |
17 | using Model;
18 |
19 |
20 | public class PolygonLineRenderer : GeometryLineRenderer
21 | {
22 |
23 |
24 | public Color lineColor;
25 | public Color boundsColor;
26 | public bool normals = false;
27 |
28 | public Polygon polygon;
29 | Source.Polygon polygonSource;
30 |
31 |
32 | void Start()
33 | {
34 | // Model reference.
35 | polygonSource = GetComponent();
36 |
37 | if (polygonSource != null)
38 | { polygon = polygonSource.polygon; }
39 | }
40 |
41 | protected override void OnDraw()
42 | {
43 | if (polygonSource != null)
44 | { polygon = polygonSource.polygon; }
45 |
46 | if (polygon == null) return; // Only having polygon
47 |
48 | if (polygonSource.coordinates == Source.Polygon.Coordinates.World)
49 | {
50 | DrawRect(polygon.bounds, boundsColor);
51 | DrawPolygon(polygon, lineColor, normals);
52 | }
53 | else
54 | {
55 | DrawRectWithTransform(polygon.bounds, boundsColor, this.transform);
56 | DrawPolygonWithTransform(polygon, lineColor, this.transform, normals);
57 | }
58 | }
59 | }
60 | }
61 | #endif
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_2.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 2. Polygon permiter-Point containment (precise)
22 | ///
23 | public class Controller_2 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public float accuracy = 1.0f;
31 | private float _previousAccuracy;
32 |
33 | public Source.Polygon polygonSource;
34 | public GameObject pointSource;
35 | public PolygonLineRenderer polygonRenderer;
36 |
37 | private Polygon polygon { get { return polygonSource.polygon; } }
38 | private Vector2 point { get { return pointSource.transform.position.xy(); } }
39 |
40 |
41 | void Update()
42 | { RenderTestResult(PointContainmentTest()); }
43 |
44 | bool PointContainmentTest()
45 | {
46 | return polygon.PermiterContainsPoint(point, accuracy, Segment.ContainmentMethod.Precise);
47 | }
48 |
49 | void RenderTestResult(bool testResult)
50 | {
51 | Color color = (testResult) ? passingColor : defaultColor;
52 |
53 | // Layout colors.
54 | polygonRenderer.lineColor = color;
55 | pointSource.GetComponent().material.color = color;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_0.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 0. Polygon-Point containment
22 | ///
23 | public class Controller_0 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public Source.Polygon polygonSource;
31 | public GameObject[] pointObjects;
32 | public PolygonLineRenderer polygonRenderer;
33 |
34 | Polygon polygon { get { return polygonSource.polygon; } }
35 |
36 |
37 | void Update()
38 | { RenderTestResult(PointContainmentTest()); }
39 |
40 | bool PointContainmentTest()
41 | {
42 | bool containsAllPoints = true;
43 | foreach (GameObject eachPointObject in pointObjects)
44 | {
45 | Vector2 eachPoint = eachPointObject.transform.position.xy();
46 | containsAllPoints &= polygon.ContainsPoint(eachPoint);
47 | }
48 | return containsAllPoints;
49 | }
50 |
51 | void RenderTestResult(bool testResult)
52 | {
53 | Color color = (testResult) ? passingColor : defaultColor;
54 |
55 | // Layout colors.
56 | polygonRenderer.lineColor = color;
57 | foreach (GameObject eachPointObject in pointObjects)
58 | { eachPointObject.GetComponent().material.color = color; }
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_1.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 |
18 |
19 | ///
20 | /// 1. Polygon-Segment intersection
21 | ///
22 | public class Controller_1 : MonoBehaviour
23 | {
24 |
25 |
26 | public Color defaultColor;
27 | public Color passingColor;
28 |
29 | public Source.Polygon polygonSource;
30 | public Source.Segment segmentSourceA;
31 | public Source.Segment segmentSourceB;
32 | public PolygonLineRenderer polygonRenderer;
33 | public SegmentLineRenderer segmentRendererA;
34 | public SegmentLineRenderer segmentRendererB;
35 |
36 | private Model.Polygon polygon { get { return polygonSource.polygon; } }
37 | private Model.Segment segment_a { get { return segmentSourceA.segment; } }
38 | private Model.Segment segment_b { get { return segmentSourceB.segment; } }
39 |
40 |
41 | void Update()
42 | { RenderTestResult(SegmentIntersectingTest()); }
43 |
44 | bool SegmentIntersectingTest()
45 | {
46 | return (
47 | polygon.IsIntersectingWithSegment(segment_a) ||
48 | polygon.IsIntersectingWithSegment(segment_b)
49 | );
50 | }
51 |
52 | void RenderTestResult(bool testResult)
53 | {
54 | Color color = (testResult) ? passingColor : defaultColor;
55 |
56 | // Layout colors.
57 | polygonRenderer.lineColor = color;
58 | segmentRendererA.lineColor = color;
59 | segmentRendererB.lineColor = color;
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Extensions/Vector2.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using UnityEngine;
10 |
11 |
12 | namespace EPPZ.Geometry
13 | {
14 |
15 |
16 | public static class Vector2_Extensions
17 | {
18 |
19 |
20 | public static Vector2 Rotated(this Vector2 this_, float degrees)
21 | {
22 | // Checks.
23 | float radians = degrees * Mathf.Deg2Rad;
24 | if (radians == 0.0f) return this_;
25 | if (radians == (Mathf.PI * 2.0f)) return this_;
26 |
27 | float sin = Mathf.Sin(radians);
28 | float cos = Mathf.Cos(radians);
29 |
30 | Vector2 rotated = new Vector2(
31 | (cos * this_.x) - (sin * this_.y),
32 | (sin * this_.x) + (cos * this_.y)
33 | );
34 |
35 | return rotated;
36 | }
37 |
38 | public static Vector2 RotatedAround(this Vector2 this_, Vector2 around, float degrees)
39 | {
40 | // Checks.
41 | float radians = degrees * Mathf.Deg2Rad;
42 | if (radians == 0.0f) return this_;
43 | if (radians == (Mathf.PI * 2.0f)) return this_;
44 |
45 | Vector2 τposition = this_ - around;
46 | τposition = τposition.Rotated(degrees);
47 | τposition = around + τposition;
48 |
49 | return τposition;
50 | }
51 |
52 | public static float AngleTo(this Vector2 this_, Vector3 to)
53 | { return this_.AngleTo((Vector2)to); }
54 |
55 | public static float AngleTo(this Vector2 this_, Vector2 to)
56 | {
57 | Vector2 direction = to - this_;
58 | float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
59 | if (angle < 0.0f) angle += 360.0f;
60 | return angle;
61 | }
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 643497948b6324a888e28fc3cd1cb964
3 | timeCreated: 1498004404
4 | licenseType: Free
5 | TextureImporter:
6 | fileIDToRecycleName: {}
7 | serializedVersion: 4
8 | mipmaps:
9 | mipMapMode: 0
10 | enableMipMap: 1
11 | sRGBTexture: 1
12 | linearTexture: 0
13 | fadeOut: 0
14 | borderMipMap: 0
15 | mipMapsPreserveCoverage: 0
16 | alphaTestReferenceValue: 0.5
17 | mipMapFadeDistanceStart: 1
18 | mipMapFadeDistanceEnd: 3
19 | bumpmap:
20 | convertToNormalMap: 0
21 | externalNormalMap: 0
22 | heightScale: 0.25
23 | normalMapFilter: 0
24 | isReadable: 0
25 | grayScaleToAlpha: 0
26 | generateCubemap: 6
27 | cubemapConvolution: 0
28 | seamlessCubemap: 0
29 | textureFormat: 1
30 | maxTextureSize: 2048
31 | textureSettings:
32 | serializedVersion: 2
33 | filterMode: -1
34 | aniso: -1
35 | mipBias: -1
36 | wrapU: -1
37 | wrapV: -1
38 | wrapW: -1
39 | nPOTScale: 1
40 | lightmap: 0
41 | compressionQuality: 50
42 | spriteMode: 0
43 | spriteExtrude: 1
44 | spriteMeshType: 1
45 | alignment: 0
46 | spritePivot: {x: 0.5, y: 0.5}
47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
48 | spritePixelsToUnits: 100
49 | alphaUsage: 1
50 | alphaIsTransparency: 1
51 | spriteTessellationDetail: -1
52 | textureType: 0
53 | textureShape: 1
54 | maxTextureSizeSet: 0
55 | compressionQualitySet: 0
56 | textureFormatSet: 0
57 | platformSettings:
58 | - buildTarget: DefaultTexturePlatform
59 | maxTextureSize: 2048
60 | textureFormat: -1
61 | textureCompression: 1
62 | compressionQuality: 50
63 | crunchedCompression: 0
64 | allowsAlphaSplitting: 0
65 | overridden: 0
66 | - buildTarget: Standalone
67 | maxTextureSize: 2048
68 | textureFormat: -1
69 | textureCompression: 1
70 | compressionQuality: 50
71 | crunchedCompression: 0
72 | allowsAlphaSplitting: 0
73 | overridden: 0
74 | - buildTarget: iPhone
75 | maxTextureSize: 2048
76 | textureFormat: -1
77 | textureCompression: 1
78 | compressionQuality: 50
79 | crunchedCompression: 0
80 | allowsAlphaSplitting: 0
81 | overridden: 0
82 | - buildTarget: Android
83 | maxTextureSize: 2048
84 | textureFormat: -1
85 | textureCompression: 1
86 | compressionQuality: 50
87 | crunchedCompression: 0
88 | allowsAlphaSplitting: 0
89 | overridden: 0
90 | spriteSheet:
91 | serializedVersion: 2
92 | sprites: []
93 | outline: []
94 | physicsShape: []
95 | spritePackingTag:
96 | userData:
97 | assetBundleName:
98 | assetBundleVariant:
99 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Winding.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d715ae3a587948808be900f38d3d902
3 | timeCreated: 1498012570
4 | licenseType: Free
5 | TextureImporter:
6 | fileIDToRecycleName: {}
7 | serializedVersion: 4
8 | mipmaps:
9 | mipMapMode: 0
10 | enableMipMap: 1
11 | sRGBTexture: 1
12 | linearTexture: 0
13 | fadeOut: 0
14 | borderMipMap: 0
15 | mipMapsPreserveCoverage: 0
16 | alphaTestReferenceValue: 0.5
17 | mipMapFadeDistanceStart: 1
18 | mipMapFadeDistanceEnd: 3
19 | bumpmap:
20 | convertToNormalMap: 0
21 | externalNormalMap: 0
22 | heightScale: 0.25
23 | normalMapFilter: 0
24 | isReadable: 0
25 | grayScaleToAlpha: 0
26 | generateCubemap: 6
27 | cubemapConvolution: 0
28 | seamlessCubemap: 0
29 | textureFormat: 1
30 | maxTextureSize: 2048
31 | textureSettings:
32 | serializedVersion: 2
33 | filterMode: -1
34 | aniso: -1
35 | mipBias: -1
36 | wrapU: -1
37 | wrapV: -1
38 | wrapW: -1
39 | nPOTScale: 1
40 | lightmap: 0
41 | compressionQuality: 50
42 | spriteMode: 0
43 | spriteExtrude: 1
44 | spriteMeshType: 1
45 | alignment: 0
46 | spritePivot: {x: 0.5, y: 0.5}
47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
48 | spritePixelsToUnits: 100
49 | alphaUsage: 1
50 | alphaIsTransparency: 1
51 | spriteTessellationDetail: -1
52 | textureType: 0
53 | textureShape: 1
54 | maxTextureSizeSet: 0
55 | compressionQualitySet: 0
56 | textureFormatSet: 0
57 | platformSettings:
58 | - buildTarget: DefaultTexturePlatform
59 | maxTextureSize: 2048
60 | textureFormat: -1
61 | textureCompression: 1
62 | compressionQuality: 50
63 | crunchedCompression: 0
64 | allowsAlphaSplitting: 0
65 | overridden: 0
66 | - buildTarget: Standalone
67 | maxTextureSize: 2048
68 | textureFormat: -1
69 | textureCompression: 1
70 | compressionQuality: 50
71 | crunchedCompression: 0
72 | allowsAlphaSplitting: 0
73 | overridden: 0
74 | - buildTarget: iPhone
75 | maxTextureSize: 2048
76 | textureFormat: -1
77 | textureCompression: 1
78 | compressionQuality: 50
79 | crunchedCompression: 0
80 | allowsAlphaSplitting: 0
81 | overridden: 0
82 | - buildTarget: Android
83 | maxTextureSize: 2048
84 | textureFormat: -1
85 | textureCompression: 1
86 | compressionQuality: 50
87 | crunchedCompression: 0
88 | allowsAlphaSplitting: 0
89 | overridden: 0
90 | spriteSheet:
91 | serializedVersion: 2
92 | sprites: []
93 | outline: []
94 | physicsShape: []
95 | spritePackingTag:
96 | userData:
97 | assetBundleName:
98 | assetBundleVariant:
99 |
--------------------------------------------------------------------------------
/Source/Mesh.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 |
12 |
13 | namespace EPPZ.Geometry.Source
14 | {
15 |
16 |
17 | using AddOns;
18 |
19 |
20 | public class Mesh : MonoBehaviour
21 | {
22 |
23 |
24 | public TriangulatorType triangulator = TriangulatorType.Dwyer;
25 | public Color color = Color.white;
26 |
27 | public enum UpdateMode { Awake, Update, LateUpdate };
28 | public UpdateMode update = UpdateMode.Awake;
29 |
30 | Source.Polygon polygonSource;
31 | Model.Polygon polygon;
32 | MeshFilter meshFilter;
33 |
34 |
35 | void Awake()
36 | {
37 | polygonSource = GetComponent();
38 | meshFilter = GetComponent();
39 |
40 | if (meshFilter == null)
41 | {
42 | Debug.LogWarning("No MeshFilter component on \""+name+"\" (for PolygonMesh to use as output). Disabled GameObject.");
43 | gameObject.SetActive(false);
44 | }
45 |
46 | if (polygonSource != null)
47 | { polygon = polygonSource.polygon; }
48 |
49 | if (update == UpdateMode.Awake)
50 | { CreateMesh(); }
51 | }
52 |
53 | void Update()
54 | {
55 | if (update == UpdateMode.Update)
56 | { CreateMesh(); }
57 | }
58 |
59 | void LateUpdate()
60 | {
61 | if (update == UpdateMode.LateUpdate)
62 | { CreateMesh(); }
63 | }
64 |
65 | void CreateMesh()
66 | {
67 | if (polygonSource != null)
68 | { polygon = polygonSource.polygon; }
69 |
70 | meshFilter.mesh = polygon.Mesh(color, triangulator);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Source/Polygon.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 | using UnityEngine.Serialization;
11 |
12 |
13 |
14 | namespace EPPZ.Geometry.Source
15 | {
16 |
17 |
18 | public class Polygon : MonoBehaviour
19 | {
20 |
21 |
22 | [UnityEngine.Serialization.FormerlySerializedAs("pointTransforms")]
23 | public Transform[] points;
24 | public float offset = 0.0f;
25 |
26 | public enum UpdateMode { Awake, Update, LateUpdate };
27 | public UpdateMode update = UpdateMode.Awake;
28 |
29 | public enum Coordinates { World, Local }
30 | public Coordinates coordinates = Coordinates.World;
31 |
32 | Model.Polygon _polygon;
33 | Model.Polygon _offsetPolygon;
34 | public Model.Polygon polygon { get { return (offset != 0.0f) ? _offsetPolygon : _polygon; } }
35 |
36 |
37 | void Awake()
38 | {
39 | // Construct a polygon model from transforms (if not created by a root polygon already).
40 | if (_polygon == null) _polygon = Model.Polygon.PolygonWithSource(this);
41 | if (offset != 0.0f) _offsetPolygon = _polygon.OffsetPolygon(offset);
42 | }
43 |
44 | void Update()
45 | {
46 | if (update == UpdateMode.Update)
47 | { UpdateModel(); }
48 | }
49 |
50 | void LateUpdate()
51 | {
52 | if (update == UpdateMode.LateUpdate)
53 | { UpdateModel(); }
54 | }
55 |
56 | void UpdateModel()
57 | {
58 | // Update polygon model with transforms, also update calculations.
59 | _polygon.UpdatePointPositionsWithSource(this);
60 | if (offset != 0.0f) _offsetPolygon = _polygon.OffsetPolygon(offset);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Inspector/Editor/PolygonInspector.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 | using UnityEditor;
11 |
12 |
13 | namespace EPPZ.Geometry.Inspector.Editor
14 | {
15 |
16 |
17 | using Model;
18 |
19 |
20 | [CustomEditor(typeof(EPPZ.Geometry.Inspector.PolygonInspector))]
21 | public class PolygonInspector : UnityEditor.Editor
22 | {
23 |
24 |
25 | public override void OnInspectorGUI()
26 | {
27 | // References.
28 | Inspector.PolygonInspector polygonInspector = (Inspector.PolygonInspector)target;
29 | Polygon polygon = polygonInspector.polygon;
30 | if (polygon == null) return;
31 | Edge edge = polygon.edges[polygonInspector.currentEdgeIndex];
32 | if (edge == null) return;
33 |
34 | if (GUILayout.Button("-"))
35 | {
36 | polygonInspector.currentEdgeIndex = edge.previousEdge.index;
37 | edge = polygon.edges[polygonInspector.currentEdgeIndex];
38 |
39 | ShowUpEdges(edge);
40 | }
41 |
42 | if (GUILayout.Button("Show up ("+polygonInspector.currentEdgeIndex.ToString()+")"))
43 | {
44 | ShowUpEdges(edge);
45 | }
46 |
47 | if (GUILayout.Button("+"))
48 | {
49 | polygonInspector.currentEdgeIndex = edge.nextEdge.index;
50 | edge = polygon.edges[polygonInspector.currentEdgeIndex];
51 |
52 | ShowUpEdges(edge);
53 | }
54 | }
55 |
56 | private void ShowUpEdges(Edge edge)
57 | {
58 | Debug.DrawLine(edge.previousEdge.a, edge.previousEdge.b, Color.blue, 1.0f);
59 | Debug.DrawLine(edge.a, edge.b, Color.red, 1.0f);
60 | Debug.DrawLine(edge.nextEdge.a, edge.nextEdge.b, Color.green, 1.0f);
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/Lines/ExtendedPolygonLineRenderer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | #if EPPZ_LINES
9 | using UnityEngine;
10 | using System.Collections;
11 |
12 |
13 | namespace EPPZ.Geometry.Lines
14 | {
15 |
16 |
17 | public class ExtendedPolygonLineRenderer : PolygonLineRenderer
18 | {
19 |
20 |
21 | public GameObject windingObject;
22 | public TextMesh areaTextMesh;
23 |
24 | private float _previousArea;
25 | private Model.Polygon.Winding _previousWindingDirection;
26 |
27 |
28 | void Start()
29 | {
30 | // Model reference.
31 | Source.Polygon polygonSource = GetComponent();
32 | if (polygonSource != null)
33 | { polygon = polygonSource.polygon; }
34 | }
35 |
36 | void Update()
37 | {
38 | if (polygon == null) return; // Only having polygon
39 |
40 | // Layout winding direction object if any.
41 | bool hasWindingDirectionObject = (windingObject != null);
42 | bool windingChanged = (polygon.winding != _previousWindingDirection);
43 | if (hasWindingDirectionObject && windingChanged)
44 | {
45 | windingObject.transform.localScale = (polygon.isCW) ? Vector3.one : new Vector3 (1.0f, -1.0f, 1.0f);
46 | windingObject.transform.rotation = (polygon.isCW) ? Quaternion.identity : Quaternion.Euler( new Vector3 (0.0f, 0.0f, 90.0f) );
47 | }
48 |
49 | // Layout area text mesh if any.
50 | bool hasAreaTextMesh = (areaTextMesh != null);
51 | bool areaChanged = (polygon.area != _previousArea);
52 | if (hasAreaTextMesh && areaChanged)
53 | {
54 | areaTextMesh.text = polygon.area.ToString();
55 | }
56 |
57 | // Track.
58 | _previousWindingDirection = polygon.winding;
59 | _previousArea = polygon.area;
60 | }
61 | }
62 | }
63 | #endif
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_8.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 8. Segment-Segment intersection point
22 | ///
23 | public class Controller_8 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public float accuracy = 0.0f;
31 |
32 | public Source.Segment segmentSourceA;
33 | public Source.Segment segmentSourceB;
34 | public SegmentLineRenderer segmentRendererA;
35 | public SegmentLineRenderer segmentRendererB;
36 |
37 | public GameObject intersectionPointObject;
38 |
39 | private Segment segment_a { get { return segmentSourceA.segment; } }
40 | private Segment segment_b { get { return segmentSourceB.segment; } }
41 |
42 |
43 | void Update()
44 | { RenderTestResult(SegmentIntersectionTest()); }
45 |
46 | bool SegmentIntersectionTest()
47 | {
48 | Vector2 intersectionPoint;
49 | bool isIntersecting = segment_a.IntersectionWithSegmentWithAccuracy(segment_b, accuracy, out intersectionPoint);
50 | if (isIntersecting)
51 | {
52 | intersectionPointObject.transform.position = new Vector3(
53 | intersectionPoint.x,
54 | intersectionPoint.y,
55 | intersectionPointObject.transform.position.z
56 | ); // Align point
57 | }
58 |
59 | return isIntersecting;
60 | }
61 |
62 | void RenderTestResult(bool testResult)
63 | {
64 | Color color = (testResult) ? passingColor : defaultColor;
65 |
66 | // Layout color.
67 | segmentRendererA.lineColor = color;
68 | segmentRendererB.lineColor = color;
69 |
70 | // Show / hide intersection point.
71 | intersectionPointObject.GetComponent().enabled = testResult;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_4.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 4. Polygon-Segment containment
22 | ///
23 | public class Controller_4 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public Source.Polygon starSource;
31 | public Source.Polygon squareSource;
32 | public PolygonLineRenderer starRenderer;
33 | public PolygonLineRenderer squareRenderer;
34 |
35 | private Polygon star { get { return starSource.polygon; } }
36 | private Polygon square { get { return squareSource.polygon; } }
37 |
38 |
39 | void Update()
40 | { RenderTestResult(IsSegmentsInsideTest()); }
41 |
42 | bool IsSegmentsInsideTest()
43 | {
44 | // Point containment.
45 | bool pointContainment = true;
46 | square.EnumeratePoints((Vector2 eachPoint) =>
47 | {
48 | pointContainment &= star.ContainsPoint(eachPoint);
49 | });
50 |
51 | // Segment-Polygon intersecion, Segment endpoint-permiter contaimnent.
52 | bool segmentIntersecting = false;
53 | bool permiterContainsSegment = false;
54 | foreach (Edge eachEdge in square.edges)
55 | {
56 | permiterContainsSegment |= star.PermiterContainsPoint(eachEdge.a) || star.PermiterContainsPoint(eachEdge.b);
57 | segmentIntersecting |= star.IsIntersectingWithSegment(eachEdge);
58 | }
59 |
60 | // Polygon inside test.
61 | bool polygonInside = pointContainment && segmentIntersecting == false && permiterContainsSegment == false;
62 |
63 | return polygonInside;
64 | }
65 |
66 | void RenderTestResult(bool testResult)
67 | {
68 | Color color = (testResult) ? passingColor : defaultColor;
69 |
70 | // Layout colors.
71 | starRenderer.lineColor = color;
72 | squareRenderer.lineColor = color;
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_6.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 |
17 | using Lines;
18 | using Model;
19 |
20 |
21 | ///
22 | /// 6. Vertex facing
23 | ///
24 | public class Controller_6 : MonoBehaviour
25 | {
26 |
27 |
28 | public Color defaultColor;
29 | public Color passingColor;
30 |
31 | public CornerLineRenderer cornerRenderer;
32 | public Renderer normalPointRenderer;
33 |
34 | public Transform[] segmentATransforms;
35 | public Transform[] segmentBTransforms;
36 |
37 | public Transform[] normalTransforms;
38 |
39 | private Segment segmentA;
40 | private Segment segmentB;
41 | private Segment normal;
42 |
43 | void Start()
44 | {
45 | // Create models.
46 | segmentA = Segment.SegmentWithPointTransforms(segmentATransforms);
47 | segmentB = Segment.SegmentWithPointTransforms(segmentBTransforms);
48 | normal = Segment.SegmentWithPointTransforms(normalTransforms);
49 |
50 | // Feed renderer.
51 | cornerRenderer.segmentA = segmentA;
52 | cornerRenderer.segmentB = segmentB;
53 | cornerRenderer.normal = normal;
54 | }
55 |
56 | void Update()
57 | {
58 | // Update model.
59 | segmentA.UpdateWithTransforms(segmentATransforms);
60 | segmentB.UpdateWithTransforms(segmentBTransforms);
61 | normal.UpdateWithTransforms(normalTransforms);
62 |
63 | // Test.
64 | RenderTestResult(NormalFacingTest());
65 | }
66 |
67 | bool NormalFacingTest()
68 | {
69 | Vector2 point = normal.b;
70 | bool acute = segmentA.IsPointLeft(segmentB.b);
71 | bool leftA = segmentA.IsPointLeft(point);
72 | bool leftB = segmentB.IsPointLeft(point);
73 | bool outward = (acute) ? leftA && leftB : leftA || leftB;
74 | bool inward = !outward;
75 | return inward;
76 | }
77 |
78 | void RenderTestResult(bool testResult)
79 | {
80 | Color color = (testResult) ? passingColor : defaultColor;
81 |
82 | // Layout color.
83 | cornerRenderer.segmentNormalColor = color;
84 | normalPointRenderer.material.color = color;
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/Scenes/Controllers/Controller_5.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Scenes
13 | {
14 |
15 |
16 | using Lines;
17 | using Model;
18 |
19 |
20 | ///
21 | /// 5. Polygon-Polygon containment
22 | ///
23 | public class Controller_5 : MonoBehaviour
24 | {
25 |
26 |
27 | public Color defaultColor;
28 | public Color passingColor;
29 |
30 | public Source.Polygon starSource;
31 | public Source.Polygon squareSource;
32 | public PolygonLineRenderer starRenderer;
33 | public PolygonLineRenderer squareRenderer;
34 |
35 | private Polygon star { get { return starSource.polygon; } }
36 | private Polygon square { get { return squareSource.polygon; } }
37 |
38 |
39 | void Update()
40 | { RenderTestResult(IsPolygonInsideTest()); }
41 |
42 | bool IsPolygonInsideTest()
43 | {
44 | // Point containment.
45 | bool pointContainment = true;
46 | square.EnumeratePointsRecursive((Vector2 eachPoint) =>
47 | {
48 | pointContainment &= star.ContainsPoint(eachPoint);
49 | });
50 |
51 | // Segment-Polygon intersecion, Segment endpoint-permiter contaimnent.
52 | bool segmentIntersecting = false;
53 | bool permiterContainsSegment = false;
54 | foreach (Edge eachEdge in square.edges)
55 | {
56 | permiterContainsSegment |= star.PermiterContainsPoint(eachEdge.a) || star.PermiterContainsPoint(eachEdge.b);
57 | segmentIntersecting |= star.IsIntersectingWithSegment(eachEdge);
58 | }
59 |
60 | // A polygon contains another polygon, when
61 | // - other polygon vertices are contained by polygon,
62 | // - other polygon segments are not intersecting with polygon,
63 | // - other polygon vertices are not contained by polygon permiter.
64 | bool polygonInside = (
65 | pointContainment &&
66 | segmentIntersecting == false &&
67 | permiterContainsSegment == false
68 | );
69 |
70 | return polygonInside;
71 | }
72 |
73 | void RenderTestResult(bool testResult)
74 | {
75 | Color color = (testResult) ? passingColor : defaultColor;
76 |
77 | // Layout colors.
78 | starRenderer.lineColor = color;
79 | squareRenderer.lineColor = color;
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/Lines/GeometryLineRenderer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | #if EPPZ_LINES
9 | using UnityEngine;
10 | using System.Collections;
11 |
12 |
13 | namespace EPPZ.Geometry.Lines
14 | {
15 |
16 |
17 | using EPPZ.Lines;
18 | using Model;
19 |
20 |
21 | public class GeometryLineRenderer : DirectLineRenderer
22 | {
23 |
24 |
25 | protected void DrawSegment(Segment segment, Color color, bool drawNormals = false)
26 | {
27 | DrawLine(segment.a, segment.b, color);
28 | if (drawNormals)
29 | {
30 | Vector2 halfie = segment.a + ((segment.b - segment.a) / 2.0f);
31 | DrawLine(halfie, halfie + segment.normal * 0.1f, color);
32 | }
33 | }
34 |
35 | protected void DrawSegmentWithTransform(Segment segment, Color color, Transform transform_, bool drawNormals = false)
36 | {
37 | DrawLineWithTransform(segment.a, segment.b, color, transform_);
38 | if (drawNormals)
39 | {
40 | Vector2 halfie = segment.a + ((segment.b - segment.a) / 2.0f);
41 | DrawLineWithTransform(halfie, halfie + segment.normal * 0.1f, color, transform_);
42 | }
43 | }
44 |
45 | protected void DrawPolygon(Polygon polygon, Color color)
46 | { polygon.EnumerateEdgesRecursive((Edge eachEdge) => DrawLine(eachEdge.a, eachEdge.b, color)); }
47 |
48 | protected void DrawPolygon(Polygon polygon, Color color, bool drawNormals)
49 | {
50 | polygon.EnumerateEdgesRecursive((Edge eachEdge) =>
51 | {
52 | DrawLine(eachEdge.a, eachEdge.b, color);
53 | if (drawNormals)
54 | {
55 | Vector2 halfie = eachEdge.a + ((eachEdge.b - eachEdge.a) / 2.0f);
56 | DrawLine(halfie, halfie + eachEdge.normal * 0.1f, color);
57 | }
58 | });
59 | }
60 |
61 | protected void DrawPolygonWithTransform(Polygon polygon, Color color, Transform transform_)
62 | { DrawPolygonWithTransform(polygon, color, transform_, false); }
63 |
64 | protected void DrawPolygonWithTransform(Polygon polygon, Color color, Transform transform_, bool drawNormals)
65 | {
66 | polygon.EnumerateEdgesRecursive((Edge eachEdge) =>
67 | {
68 | DrawLineWithTransform(eachEdge.a, eachEdge.b, color, transform_);
69 | if (drawNormals)
70 | {
71 | Vector2 halfie = eachEdge.a + ((eachEdge.b - eachEdge.a) / 2.0f);
72 | DrawLineWithTransform(halfie, halfie + eachEdge.normal * 0.1f, color, transform_);
73 | }
74 | });
75 | }
76 | }
77 | }
78 | #endif
79 |
80 |
--------------------------------------------------------------------------------
/AddOns/ClipperAddOns.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using UnityEngine;
12 |
13 |
14 | namespace EPPZ.Geometry.AddOns
15 | {
16 |
17 |
18 | using System.Linq;
19 | using ClipperLib;
20 |
21 |
22 | // Clipper definitions.
23 | using Path = List;
24 | using Paths = List>;
25 |
26 |
27 | using Model;
28 |
29 |
30 | public static class ClipperAddOns
31 | {
32 |
33 |
34 | #region Polygon
35 |
36 | public static Polygon PolygonFromClipperPaths(Paths paths, float scale)
37 | {
38 | Polygon polygon = null;
39 | for (int index = 0; index < paths.Count; index++)
40 | {
41 | Path eachPath = paths[index];
42 | Polygon eachPolygon = PolygonFromClipperPath(eachPath, scale);
43 |
44 | if (index == 0)
45 | { polygon = Polygon.PolygonWithPoints(eachPolygon.points); } // Parent polygon
46 | else
47 | { polygon.AddPolygon(eachPolygon); } // Child polygons
48 | }
49 | return polygon;
50 | }
51 |
52 | public static Polygon PolygonFromClipperPath(Path path, float scale)
53 | {
54 | List points = new List();
55 | for (int index = path.Count - 1; index >= 0; index--) // Reverse enumeration (to flip normals)
56 | {
57 | IntPoint eachPoint = path[index];
58 | points.Add(new Vector2(eachPoint.X / scale, eachPoint.Y / scale));
59 | }
60 | return Polygon.PolygonWithPointList(points);
61 | }
62 |
63 | public static Paths ClipperPaths(this Polygon this_, float scale)
64 | {
65 | Paths paths = new Paths();
66 | this_.EnumeratePolygons((Polygon eachPolygon) =>
67 | {
68 | paths.Add(eachPolygon.ClipperPath(scale));
69 | });
70 | return paths;
71 | }
72 |
73 | public static Path ClipperPath(this Polygon this_, float scale)
74 | {
75 | Path path = new Path();
76 | this_.EnumeratePoints((Vector2 eachPoint) =>
77 | {
78 | path.Add(new IntPoint(
79 | eachPoint.x * scale,
80 | eachPoint.y * scale
81 | ));
82 | });
83 | return path;
84 | }
85 |
86 | #endregion
87 |
88 |
89 | #region Generic
90 |
91 | public static Vector2[] PointsFromClipperPath(Path path, float scale)
92 | {
93 | List points = new List();
94 | for (int index = path.Count - 1; index >= 0; index--) // Reverse enumeration (to flip normals)
95 | {
96 | IntPoint eachPoint = path[index];
97 | points.Add(new Vector2(eachPoint.X / scale, eachPoint.Y / scale));
98 | }
99 | return points.ToArray();
100 | }
101 |
102 | #endregion
103 |
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Scenes/Animations/eppz! Geometry Drift.anim:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!74 &7400000
4 | AnimationClip:
5 | m_ObjectHideFlags: 0
6 | m_PrefabParentObject: {fileID: 0}
7 | m_PrefabInternal: {fileID: 0}
8 | m_Name: eppz! Geometry Drift
9 | serializedVersion: 6
10 | m_Legacy: 1
11 | m_Compressed: 0
12 | m_UseHighQualityCurve: 1
13 | m_RotationCurves: []
14 | m_CompressedRotationCurves: []
15 | m_EulerCurves: []
16 | m_PositionCurves:
17 | - curve:
18 | serializedVersion: 2
19 | m_Curve:
20 | - serializedVersion: 2
21 | time: 0
22 | value: {x: 6, y: 0, z: 0}
23 | inSlope: {x: 0, y: 0, z: 0}
24 | outSlope: {x: -0.3, y: -0, z: -0}
25 | tangentMode: 0
26 | - serializedVersion: 2
27 | time: 40
28 | value: {x: -6, y: 0, z: 0}
29 | inSlope: {x: -0.3, y: 0, z: 0}
30 | outSlope: {x: 0, y: 0, z: 0}
31 | tangentMode: 0
32 | m_PreInfinity: 2
33 | m_PostInfinity: 2
34 | m_RotationOrder: 4
35 | path:
36 | m_ScaleCurves: []
37 | m_FloatCurves: []
38 | m_PPtrCurves: []
39 | m_SampleRate: 60
40 | m_WrapMode: 2
41 | m_Bounds:
42 | m_Center: {x: 0, y: 0, z: 0}
43 | m_Extent: {x: 0, y: 0, z: 0}
44 | m_ClipBindingConstant:
45 | genericBindings: []
46 | pptrCurveMapping: []
47 | m_AnimationClipSettings:
48 | serializedVersion: 2
49 | m_AdditiveReferencePoseClip: {fileID: 0}
50 | m_AdditiveReferencePoseTime: 0
51 | m_StartTime: 0
52 | m_StopTime: 40
53 | m_OrientationOffsetY: 0
54 | m_Level: 0
55 | m_CycleOffset: 0
56 | m_HasAdditiveReferencePose: 0
57 | m_LoopTime: 1
58 | m_LoopBlend: 0
59 | m_LoopBlendOrientation: 0
60 | m_LoopBlendPositionY: 0
61 | m_LoopBlendPositionXZ: 0
62 | m_KeepOriginalOrientation: 0
63 | m_KeepOriginalPositionY: 1
64 | m_KeepOriginalPositionXZ: 0
65 | m_HeightFromFeet: 0
66 | m_Mirror: 0
67 | m_EditorCurves:
68 | - curve:
69 | serializedVersion: 2
70 | m_Curve:
71 | - serializedVersion: 2
72 | time: 0
73 | value: 6
74 | inSlope: 0
75 | outSlope: -0.3
76 | tangentMode: 65
77 | - serializedVersion: 2
78 | time: 40
79 | value: -6
80 | inSlope: -0.3
81 | outSlope: 0
82 | tangentMode: 5
83 | m_PreInfinity: 2
84 | m_PostInfinity: 2
85 | m_RotationOrder: 4
86 | attribute: m_LocalPosition.x
87 | path:
88 | classID: 4
89 | script: {fileID: 0}
90 | - curve:
91 | serializedVersion: 2
92 | m_Curve:
93 | - serializedVersion: 2
94 | time: 0
95 | value: 0
96 | inSlope: 0
97 | outSlope: -0
98 | tangentMode: 65
99 | - serializedVersion: 2
100 | time: 40
101 | value: 0
102 | inSlope: 0
103 | outSlope: 0
104 | tangentMode: 5
105 | m_PreInfinity: 2
106 | m_PostInfinity: 2
107 | m_RotationOrder: 4
108 | attribute: m_LocalPosition.y
109 | path:
110 | classID: 4
111 | script: {fileID: 0}
112 | - curve:
113 | serializedVersion: 2
114 | m_Curve:
115 | - serializedVersion: 2
116 | time: 0
117 | value: 0
118 | inSlope: 0
119 | outSlope: -0
120 | tangentMode: 65
121 | - serializedVersion: 2
122 | time: 40
123 | value: 0
124 | inSlope: 0
125 | outSlope: 0
126 | tangentMode: 5
127 | m_PreInfinity: 2
128 | m_PostInfinity: 2
129 | m_RotationOrder: 4
130 | attribute: m_LocalPosition.z
131 | path:
132 | classID: 4
133 | script: {fileID: 0}
134 | m_EulerEditorCurves: []
135 | m_HasGenericRootTransform: 0
136 | m_HasMotionFloatCurves: 0
137 | m_GenerateMotionCurves: 0
138 | m_Events: []
139 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # eppz! `Geometry`
2 |
3 | * 1.0.13
4 |
5 | + Included `meta` files to fix example scenes
6 |
7 | * 1.0.11
8 |
9 | + Force text asset serialization
10 |
11 | * 1.0.1
12 |
13 | + Test scenes
14 | + `11. Polygon triangulation (1)`
15 | + `11. Polygon triangulation (2)`
16 | + `Polygon.UpdatePointPositionsWithSource()`
17 | + Update child transforms
18 |
19 | * 1.0.0
20 |
21 | + Triangulation
22 | + Resolved issue with inner triangles
23 | + Skip triangles if centroid not contained by polygon
24 | + `Source`
25 | + `Mesh`
26 | + Component to feed `MeshFilter` components
27 | + `Polygon` / `Segment`
28 | + Added `coordinates` to process `World` / `Local` coordinates
29 |
30 | * 0.9.7
31 |
32 | + Triangulation
33 | + Feature ready (`Triangle.Net` beta 4 hooked up)
34 | + API is not quiet done yet
35 |
36 | * 0.9.5
37 |
38 | + Namings
39 | + Model classes namespaced into `Model`
40 | + Source classes namespaced into `Source`
41 | + `Components.PolygonSource` is `Source.Polygon`
42 | + `Components.SegmentSource` is `Source.Segment`
43 | + `pointTransforms` is `points`
44 | + Updated controllers in `Scenes/Controllers`
45 |
46 | * 0.9.0
47 |
48 | + Added `TriangleNetAddOns`
49 | + Added `UnityEngineAdOns`
50 |
51 | * 0.8.3
52 |
53 | + Added `ClipperAddOns`
54 |
55 | * 0.8.2
56 |
57 | + `PolygonSource`
58 | + Offset now can be manipulated at runtime
59 | + Maintain the original polygon, so offset polygon can be recalculated any time
60 |
61 | * 0.8.0
62 |
63 | + Test scenes
64 | `8. Segment-Segment intersection point`
65 | `9. Polygon offset`
66 | `10. Multiple polygon centroid`
67 | + `ExtendedPolygonLineRenderer`
68 | + Winding and area hooks moved down here
69 |
70 | * 0.7.0
71 |
72 | + Test scenes
73 | `4. Polygon-Segment containment`
74 | `5. Polygon-Polygon containment`
75 | `6. Vertex facing`
76 | `7. Polygon area, Polygon winding`
77 | + `Segment` (with `SegmentLineRenderer`)
78 | + Can now draw normals
79 | + `normal` and `perpendicular` calculations moved up from `Edge`
80 | + `Polygon`
81 | + Fixed `area` (so `winding`) calculations
82 |
83 | * 0.6.0
84 |
85 | + Test scenes
86 | + `5. Polygon-Polygon containment (1)`
87 | + `5. Polygon-Polygon containment (2)`
88 |
89 | * 0.5.9
90 |
91 | + Polygon / segment sources now can be updates on `Update` or `LateUpdate`
92 | + Test scenes
93 | + Updated update modes
94 |
95 | * 0.5.8
96 |
97 | + Test scenes
98 | + `3. Polygon permiter-Point containment (Default)`
99 | + `4. Polygon-Segment containment`
100 | + Polygon / segment sources use world position (!) instead local
101 | + Line renderers use world positions as well (both segment and polygon)
102 | + Polygon and segment sources can be updated on `LateUpdate()`
103 |
104 | * 0.5.7
105 |
106 | + Test scene `2. Polygon permiter-Point containment (Precise)`
107 |
108 | * 0.5.6
109 |
110 | + Test scene `1. Polygon-Segment intersection`
111 |
112 | * 0.5.5
113 |
114 | + Only calculated winding direction
115 | + Removed option to define polygon winding
116 | + Removed distinct `_signedArea`
117 | + `area` is always (!) signed
118 | + Polygon calculations grouped together
119 | + Renamed to simply `winding`
120 | + `Geometry`
121 | + `CentroidOfPolygons` use `area` directly (being always signed)
122 |
123 | * 0.5.1
124 |
125 | + Added `Lines` (renderer classes)
126 | + Added `Scenes`
127 | + Yet with a single scene `0. Polygon-point containment`
128 |
129 | * 0.5.0
130 |
131 | + Added the root `Geometry.cs` static class
132 | + Added `Vector2` / `Vector3` extensions
133 | + Added `AddOns` (yet disabled)
134 | + Added `Components`
135 | + Added `Editor` scripts
136 | + Added `Model` classes
137 | + Added regions, XML-Doc summaries
138 | + Update `README.md`
139 |
140 | * 0.0.2
141 |
142 | + Added `Clipper` submodule
143 | + Added `Triangle.NET` submodule
144 |
145 | * 0.0.1
146 |
147 | + Ignore `.meta` files (no value for script assets)
148 |
149 | * 0.0.0
150 |
151 | + Initial commit
--------------------------------------------------------------------------------
/Model/Edge.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Model
13 | {
14 |
15 |
16 | public class Edge : Segment
17 | {
18 |
19 |
20 | private int _index;
21 | public int index { get { return _index; } } // Readonly
22 | public Polygon polygon { get { return vertexA.polygon; } } // Readonly
23 |
24 | public Vertex vertexA;
25 | public Vertex vertexB;
26 |
27 |
28 | #region Factory
29 |
30 | public static Edge EdgeAtIndexWithVertices(int index, Vertex vertexA, Vertex vertexB)
31 | {
32 | Edge instance = new Edge();
33 | instance._index = index;
34 | instance.vertexA = vertexA;
35 | instance.vertexB = vertexB;
36 | return instance;
37 | }
38 |
39 | #endregion
40 |
41 |
42 | #region Override segment point accessors (perefencing polygon points directly).
43 |
44 | public override Vector2 a
45 | {
46 | get { return polygon.points[vertexA.index]; }
47 | set { polygon.points[vertexA.index] = value; }
48 | }
49 |
50 | public override Vector2 b
51 | {
52 | get { return polygon.points[vertexB.index]; }
53 | set { polygon.points[vertexB.index] = value; }
54 | }
55 |
56 | #endregion
57 |
58 |
59 | #region Accessors
60 |
61 | public Edge _previousEdge;
62 | public virtual Edge previousEdge { get { return _previousEdge; } } // Readonly
63 | public void SetPreviousEdge(Edge edge) { _previousEdge = edge; } // Explicit setter (injected at creation time)
64 |
65 | public Edge _nextEdge;
66 | public virtual Edge nextEdge { get { return _nextEdge; } } // Readonly
67 | public void SetNextEdge(Edge edge) { _nextEdge = edge; } // Explicit setter (injected at creation time)
68 |
69 | #endregion
70 |
71 |
72 | #region Polygon features
73 |
74 | public bool ForwardIntersection(out Edge intersectingEdge, out Vector2 intersectionPoint, bool checkEntirePolygonLoop)
75 | {
76 | // Default.
77 | intersectingEdge = null;
78 | intersectionPoint = Vector2.zero;
79 | bool intersecting = false;
80 |
81 | // Only if there are edges enough to test.
82 | if (this.polygon.edges.Length <= 3) return false;
83 |
84 | Edge testEdge = this.nextEdge.nextEdge; // Skip next neighbour
85 | while(true)
86 | {
87 | intersecting = this.IntersectionWithSegment(testEdge, out intersectionPoint);
88 | if (intersecting)
89 | {
90 | intersectingEdge = testEdge;
91 | break;
92 | }
93 |
94 | // Step.
95 | testEdge = testEdge.nextEdge;
96 |
97 | // End conditions.
98 | bool end;
99 | if (checkEntirePolygonLoop)
100 | {
101 | end = (testEdge == this.previousEdge.previousEdge); // Only up till the previous neighbour
102 | }
103 | else
104 | {
105 | end = (testEdge == this.polygon.edges[0].previousEdge); // Only up till the end of the polygon loop
106 | }
107 | if (end) break;
108 | }
109 |
110 | return intersecting;
111 | }
112 |
113 | #endregion
114 |
115 |
116 | }
117 | }
--------------------------------------------------------------------------------
/Model/Vertex.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 |
11 |
12 | namespace EPPZ.Geometry.Model
13 | {
14 |
15 |
16 | public class Vertex
17 | {
18 |
19 |
20 | private int _index;
21 | public int index { get { return _index; } } // Readonly
22 | private Polygon _polygon;
23 | public Polygon polygon { get { return _polygon; } } // Readonly
24 |
25 | // If `alwaysCalculate` is on, every `normal` and `bisector` property access invokes recalculation of values based on actual topology.
26 | public bool alwaysCalculate = true;
27 |
28 | private Vector2 _normal;
29 | public Vector2 normal
30 | {
31 | get
32 | {
33 | if (_normal == Vector2.zero || alwaysCalculate) { CalculateNormal(); } // Lazy calculation or force calculate on every access
34 | return _normal;
35 | }
36 |
37 | set
38 | { _normal = value; }
39 | }
40 |
41 | // Bisector is simply the sum of the neighbouring edge normals (not normalized).
42 | public Vector2 _bisector;
43 | public Vector2 bisector
44 | {
45 | get
46 | {
47 | if (_bisector == Vector2.zero || alwaysCalculate) { CalculateBisector(); } // Lazy calculation or force calculate on every access
48 | return _bisector;
49 | }
50 |
51 | set
52 | { _bisector = value; }
53 | }
54 |
55 | public void CalculateNormal()
56 | { _normal = this.bisector.normalized; }
57 |
58 | public void CalculateBisector()
59 | { _bisector = previousEdge.normal + nextEdge.normal; }
60 |
61 |
62 | #region Factory
63 |
64 | public static Vertex VertexAtIndexInPolygon(int index, Polygon polygon)
65 | {
66 | Vertex instance = new Vertex();
67 | instance._index = index;
68 | instance._polygon = polygon;
69 | return instance;
70 | }
71 |
72 | #endregion
73 |
74 |
75 | #region Accessors
76 |
77 | private Vertex _previousVertex;
78 | public virtual Vertex previousVertex { get { return _previousVertex; } } // Readonly
79 | public void SetPreviousVertex(Vertex vertex) { _previousVertex = vertex; } // Explicit setter (injected at creation time)
80 |
81 | private Vertex _nextVertex;
82 | public virtual Vertex nextVertex { get { return _nextVertex; } } // Readonly
83 | public void SetNextVertex(Vertex vertex) { _nextVertex = vertex; } // Explicit setter (injected at creation time)
84 |
85 | private Edge _previousEdge;
86 | public virtual Edge previousEdge { get { return _previousEdge; } } // Readonly
87 | public void SetPreviousEdge(Edge edge) { _previousEdge = edge; } // Explicit setter (injected at creation time)
88 |
89 | private Edge _nextEdge;
90 | public virtual Edge nextEdge { get { return _nextEdge; } } // Readonly
91 | public void SetNextEdge(Edge edge) { _nextEdge = edge; } // Explicit setter (injected at creation time)
92 |
93 | public virtual Vector2 point { get { return polygon.points[index]; } } // Readonly
94 | public float x { get { return point.x; } } // Readonly
95 | public float y { get { return point.y; } } // Readonly
96 |
97 | #endregion
98 |
99 |
100 | }
101 | }
--------------------------------------------------------------------------------
/AddOns/TriangleNetAddOns.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using UnityEngine;
12 |
13 |
14 | namespace EPPZ.Geometry.AddOns
15 | {
16 |
17 |
18 | using System.Linq;
19 |
20 | using ClipperLib;
21 | using Path = List;
22 | using Paths = List>;
23 |
24 | using Model;
25 |
26 |
27 | public static class TriangleNetAddOns
28 | {
29 |
30 |
31 | #region Polygon
32 |
33 | public static TriangleNet.Geometry.Polygon TriangleNetPolygon(this Polygon this_)
34 | {
35 | TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon();
36 |
37 | int boundary = 1;
38 | List vertices = new List();
39 | this_.EnumeratePolygons((Polygon eachPolygon) =>
40 | {
41 | // Collect vertices.
42 | vertices.Clear();
43 | eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
44 | {
45 | vertices.Add(new TriangleNet.Geometry.Vertex(
46 | (double)eachPoint.x,
47 | (double)eachPoint.y,
48 | boundary
49 | ));
50 | });
51 |
52 | // Add controur.
53 | polygon.Add(new TriangleNet.Geometry.Contour(vertices.ToArray(), boundary));
54 |
55 | // Track.
56 | boundary++;
57 | });
58 |
59 | return polygon;
60 | }
61 |
62 | #endregion
63 |
64 |
65 | #region Voronoi (beta 3)
66 |
67 | public static Rect Bounds(this TriangleNet.Voronoi.Legacy.SimpleVoronoi this_)
68 | {
69 | float xmin = float.MaxValue;
70 | float xmax = 0.0f;
71 | float ymin = float.MaxValue;
72 | float ymax = 0.0f;
73 | foreach (TriangleNet.Voronoi.Legacy.VoronoiRegion region in this_.Regions)
74 | {
75 | foreach (TriangleNet.Geometry.Point eachPoint in region.Vertices)
76 | {
77 | if (eachPoint.X > xmax) xmax = (float)eachPoint.X;
78 | if (eachPoint.X < xmin) xmin = (float)eachPoint.X;
79 | if (eachPoint.Y > ymax) ymax = (float)eachPoint.Y;
80 | if (eachPoint.Y < ymin) ymin = (float)eachPoint.Y;
81 | }
82 | }
83 | return Rect.MinMaxRect(xmin, ymin, xmax, ymax);
84 | }
85 |
86 | public static Paths ClipperPathsFromVoronoiRegions(List voronoiRegions, float scale = 1.0f)
87 | {
88 | Paths paths = new Paths();
89 |
90 | foreach (TriangleNet.Voronoi.Legacy.VoronoiRegion eachRegion in voronoiRegions)
91 | {
92 | Path eachPath = new Path();
93 | foreach (TriangleNet.Geometry.Point eachPoint in eachRegion.Vertices)
94 | {
95 | eachPath.Add(new IntPoint(
96 | eachPoint.X * scale,
97 | eachPoint.Y * scale
98 | ));
99 | }
100 | paths.Add(eachPath);
101 | }
102 | return paths;
103 | }
104 |
105 | #endregion
106 |
107 |
108 | #region Generic
109 |
110 | public static Vector2 VectorFromPoint(TriangleNet.Geometry.Point point)
111 | {
112 | return new Vector2((float)point.X, (float)point.Y);
113 | }
114 |
115 | public static Vector2[] PointsFromVertices(ICollection vertices)
116 | {
117 | Vector2[] points = new Vector2[vertices.Count];
118 | int pointIndex = 0;
119 | foreach (TriangleNet.Geometry.Point eachPoint in vertices)
120 | {
121 | points[pointIndex] = VectorFromPoint(eachPoint);
122 | pointIndex++;
123 | }
124 | return points;
125 | }
126 |
127 | #endregion
128 |
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/AddOns/UnityEngineAddOns.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using System;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using UnityEngine;
12 |
13 |
14 | namespace EPPZ.Geometry.AddOns
15 | {
16 |
17 |
18 | using TriangleNet.Geometry;
19 | using TriangleNet.Meshing;
20 | using TriangleNet.Meshing.Algorithm;
21 | using TriangleNet.Tools;
22 |
23 |
24 | public enum TriangulatorType { Incremental, Dwyer, SweepLine };
25 |
26 |
27 | public static class UnityEngineAddOns
28 | {
29 |
30 |
31 | static ITriangulator TriangulatorForType(TriangulatorType triangulator)
32 | {
33 | switch (triangulator)
34 | {
35 | case TriangulatorType.Incremental : return new Incremental();
36 | case TriangulatorType.Dwyer : return new Dwyer();
37 | case TriangulatorType.SweepLine : return new SweepLine();
38 | default : return new Dwyer();
39 | }
40 | }
41 |
42 | static bool skipCentroidTest = false; // For debugging
43 |
44 |
45 | #region Polygon
46 |
47 | public static UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, string name = "")
48 | { return this_.Mesh(Color.white, TriangulatorType.Dwyer, name); }
49 |
50 | public static UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, TriangulatorType triangulator, string name = "")
51 | { return this_.Mesh(Color.white, triangulator, name); }
52 |
53 | public static UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, Color color, TriangulatorType triangulator, string name = "")
54 | {
55 | // Create geometry.
56 | TriangleNet.Geometry.Polygon polygon = this_.TriangleNetPolygon();
57 |
58 | // Triangulate.
59 | ConstraintOptions options = new ConstraintOptions();
60 | // ConformingDelaunay
61 | // Convex
62 | // SegmentSplitting
63 | QualityOptions quality = new QualityOptions();
64 | // MinimumAngle
65 | // MaximumArea
66 | // UserTest
67 | // VariableArea
68 | // SteinerPoints
69 | IMesh triangulatedMesh = polygon.Triangulate(options, quality, TriangulatorForType(triangulator));
70 |
71 | // Counts.
72 | int vertexCount = triangulatedMesh.Vertices.Count;
73 | int triangleCount = triangulatedMesh.Triangles.Count;
74 |
75 | // Mesh store.
76 | Vector3[] _vertices = new Vector3[vertexCount];
77 | Vector2[] _uv = new Vector2[vertexCount];
78 | Vector3[] _normals = new Vector3[vertexCount];
79 | Color[] _colors = new Color[vertexCount];
80 | List _triangles = new List(); // Size may vary
81 |
82 | // Vertices.
83 | int index = 0;
84 | foreach (TriangleNet.Geometry.Vertex eachVertex in triangulatedMesh.Vertices)
85 | {
86 | _vertices[index] = new Vector3(
87 | (float)eachVertex.x,
88 | (float)eachVertex.y,
89 | 0.0f // As of 2D
90 | );
91 |
92 | _uv[index] = _vertices[index];
93 | _normals[index] = Vector3.forward;
94 | _colors[index] = color;
95 |
96 | index++;
97 | }
98 |
99 | // Triangles.
100 | foreach (TriangleNet.Topology.Triangle eachTriangle in triangulatedMesh.Triangles)
101 | {
102 | // Get vertices.
103 | Point P2 = eachTriangle.GetVertex(2);
104 | Point P1 = eachTriangle.GetVertex(1);
105 | Point P0 = eachTriangle.GetVertex(0);
106 |
107 | // Get centroid.
108 | Vector2 centroid = new Vector2(
109 | (float)(P2.X + P1.X + P0.X) / 3.0f,
110 | (float)(P2.Y + P1.Y + P0.Y) / 3.0f
111 | );
112 |
113 | // Add only if centroid contained.
114 | if (this_.ContainsPoint(centroid) || skipCentroidTest)
115 | {
116 | _triangles.Add(P2.ID);
117 | _triangles.Add(P1.ID);
118 | _triangles.Add(P0.ID);
119 | }
120 | }
121 |
122 | // Create / setup mesh.
123 | Mesh mesh = new Mesh();
124 | mesh.vertices = _vertices;
125 | mesh.uv = _uv;
126 | mesh.normals = _normals;
127 | mesh.colors = _colors;
128 | mesh.subMeshCount = 1;
129 | mesh.SetTriangles(_triangles.ToArray(), 0);
130 | mesh.name = name;
131 |
132 | return mesh;
133 | }
134 |
135 | #endregion
136 |
137 |
138 | }
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/Scenes/Materials/eppz! Geometry Star.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
80 |
--------------------------------------------------------------------------------
/Geometry.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 |
12 |
13 | namespace EPPZ.Geometry
14 | {
15 |
16 |
17 | using Model; // For `Polygon` region only
18 |
19 |
20 | public static class Geometry
21 | {
22 |
23 |
24 | #region Point
25 |
26 | // Determine if points are equal with a given accuracy.
27 | public static bool ArePointsEqualWithAccuracy(Vector2 a, Vector2 b, float accuracy)
28 | {
29 | return Vector2.Distance(a, b) <= accuracy;
30 | }
31 |
32 | // Determine winding direction of three points.
33 | public static bool ArePointsCCW(Vector2 a, Vector2 b, Vector2 c)
34 | {
35 | return ((c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x));
36 | }
37 |
38 | #endregion
39 |
40 |
41 | #region Rect / Bounds
42 |
43 | // Determine if `rect2.size` fits into `rect1`.
44 | public static bool IsRectContainsRectSizeWithAccuracy(Rect rect1, Rect rect2) // Compare sizes only
45 | {
46 | return Geometry.IsRectContainsRectSizeWithAccuracy(rect1, rect2, 0.0f);
47 | }
48 |
49 | // Determine if `rect2.size` fits into `rect1` with a given accuracy.
50 | public static bool IsRectContainsRectSizeWithAccuracy(Rect rect1, Rect rect2, float accuracy) // Compare sizes only
51 | {
52 | return (
53 | Mathf.Abs(rect1.width + accuracy * 2.0f) >= Mathf.Abs(rect2.width)) &&
54 | (Mathf.Abs(rect1.height + accuracy * 2.0f) >= Mathf.Abs(rect2.height)
55 | );
56 | }
57 |
58 | // Determine if `rect2` is contained by `rect1` (even if permiters are touching).
59 | public static bool IsRectContainsRectWithAccuracy(Rect rect1, Rect rect2)
60 | { return Geometry.IsRectContainsRectWithAccuracy(rect1, rect2, 0.0f); }
61 |
62 | // Determine if `rect2` is contained by `rect1` (even if permiters are touching) with a given accuracy.
63 | public static bool IsRectContainsRectWithAccuracy(Rect rect1, Rect rect2, float accuracy)
64 | {
65 | bool xMin = (rect1.xMin - accuracy <= rect2.xMin);
66 | bool xMax = (rect1.xMax + accuracy >= rect2.xMax);
67 | bool yMin = (rect1.yMin - accuracy <= rect2.yMin);
68 | bool yMax = (rect1.yMax + accuracy >= rect2.yMax);
69 | return xMin && xMax && yMin && yMax;
70 | }
71 |
72 | #endregion
73 |
74 |
75 | #region Line
76 |
77 | ///
78 | /// Returns intersection point of two lines (defined by segment endpoints).
79 | /// Returns zero, when segments have common points, or when a segment point lies on other.
80 | ///
81 | public static Vector2 IntersectionPointOfLines(Vector2 segment1_a, Vector2 segment1_b, Vector2 segment2_a, Vector2 segment2_b)
82 | {
83 | float crossProduct = (segment1_a.x - segment1_b.x) * (segment2_a.y - segment2_b.y) - (segment1_a.y - segment1_b.y) * (segment2_a.x - segment2_b.x);
84 | if (crossProduct == 0.0f) return Vector2.zero;
85 |
86 | float x = ((segment2_a.x - segment2_b.x) * (segment1_a.x * segment1_b.y - segment1_a.y * segment1_b.x) - (segment1_a.x - segment1_b.x) * (segment2_a.x * segment2_b.y - segment2_a.y * segment2_b.x)) / crossProduct;
87 | float y = ((segment2_a.y - segment2_b.y) * (segment1_a.x * segment1_b.y - segment1_a.y * segment1_b.x) - (segment1_a.y - segment1_b.y) * (segment2_a.x * segment2_b.y - segment2_a.y * segment2_b.x)) / crossProduct;
88 |
89 | // Skip segmental tests.
90 | // if (x < Mathf.Min(a1.x, b1.x) || x > Mathf.Max(a1.x, b1.x)) return Vector2.zero;
91 | // if (x < Mathf.Min(a2.x, b2.x) || x > Mathf.Max(a2.x, b2.x)) return Vector2.zero;
92 |
93 | return new Vector2(x, y);
94 | }
95 |
96 | // Determine point distance from line (defined by segment endpoints).
97 | public static float PointDistanceFromLine(Vector2 point, Vector2 segment_a, Vector2 segment_b)
98 | {
99 | float a_ = point.x - segment_a.x;
100 | float b_ = point.y - segment_a.y;
101 | float c_ = segment_b.x - segment_a.x;
102 | float d_ = segment_b.y - segment_a.y;
103 | return Mathf.Abs(a_ * d_ - c_ * b_) / Mathf.Sqrt(c_ * c_ + d_ * d_);
104 | }
105 |
106 | #endregion
107 |
108 |
109 | #region Segment
110 |
111 | // Determine if a given point lies on the left side of a segment (line beneath).
112 | public static bool PointIsLeftOfSegment(Vector2 point, Vector2 segment_a, Vector2 segment_b)
113 | {
114 | float crossProduct = (segment_b.x - segment_a.x) * (point.y - segment_a.y) - (segment_b.y - segment_a.y) * (point.x - segment_a.x);
115 | return (crossProduct > 0.0f);
116 | }
117 |
118 | // Determine if segments (defined by endpoints) are equal with a given accuracy.
119 | public static bool AreSegmentsEqualWithAccuracy(Vector2 segment1_a, Vector2 segment1_b, Vector2 segment2_a, Vector2 segment2_b, float accuracy)
120 | {
121 | return (
122 | (ArePointsEqualWithAccuracy(segment1_a, segment2_a, accuracy) && ArePointsEqualWithAccuracy(segment1_b, segment2_b, accuracy)) ||
123 | (ArePointsEqualWithAccuracy(segment1_a, segment2_b, accuracy) && ArePointsEqualWithAccuracy(segment1_b, segment2_a, accuracy))
124 | );
125 | }
126 |
127 | // Determine if segments (defined by endpoints) have common points with a given accuracy.
128 | public static bool HaveSegmentsCommonPointsWithAccuracy(Vector2 segment1_a, Vector2 segment1_b, Vector2 segment2_a, Vector2 segment2_b, float accuracy)
129 | {
130 | return (
131 | ArePointsEqualWithAccuracy(segment1_a, segment2_a, accuracy) ||
132 | ArePointsEqualWithAccuracy(segment1_a, segment2_b, accuracy) ||
133 | ArePointsEqualWithAccuracy(segment1_b, segment2_a, accuracy) ||
134 | ArePointsEqualWithAccuracy(segment1_b, segment2_b, accuracy)
135 | );
136 | }
137 |
138 | ///
139 | /// Determine if two segments defined by endpoints are intersecting (defined by points).
140 | /// True when the two segments are intersecting. Not true when endpoints
141 | /// are equal, nor when a point is contained by other segment.
142 | /// From http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
143 | ///
144 | public static bool AreSegmentsIntersecting(Vector2 segment1_a, Vector2 segment1_b, Vector2 segment2_a, Vector2 segment2_b)
145 | {
146 | return (
147 | (ArePointsCCW(segment1_a, segment2_a, segment2_b) != ArePointsCCW(segment1_b, segment2_a, segment2_b)) &&
148 | (ArePointsCCW(segment1_a, segment1_b, segment2_a) != ArePointsCCW(segment1_a, segment1_b, segment2_b))
149 | );
150 | }
151 |
152 | #endregion
153 |
154 |
155 | #region Polygon
156 |
157 | ///
158 | /// Test if a polygon contains the given point (checks for sub-polygons recursive).
159 | /// Uses the same Bryce boe algorythm, so considerations are the same.
160 | /// From https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
161 | ///
162 | public static bool IsPolygonContainsPoint(Polygon polygon, Vector2 point)
163 | {
164 | // Winding ray left point.
165 | Vector2 left = new Vector2(polygon.bounds.xMin - polygon.bounds.width, point.y);
166 |
167 | // Enumerate polygon segments.
168 | int windingNumber = 0;
169 | polygon.EnumerateEdgesRecursive((Edge eachEdge) =>
170 | {
171 | // Test winding ray against each polygon segment.
172 | if (AreSegmentsIntersecting(left, point, eachEdge.a, eachEdge.b))
173 | { windingNumber++; }
174 | });
175 |
176 | bool isOdd = (windingNumber % 2 != 0); // Odd winding number means point falls outside
177 | return isOdd;
178 | }
179 |
180 | public static Vector2 CentroidOfPolygons(Polygon[] polygons)
181 | {
182 | // From https://en.wikipedia.org/wiki/Centroid#By_geometric_decomposition
183 | float ΣxA = 0.0f;
184 | float ΣyA = 0.0f;
185 | float ΣA = 0.0f;
186 | foreach (Polygon eachPolygon in polygons)
187 | {
188 | // Get centroid.
189 | Vector2 eachCentroid = eachPolygon.centroid;
190 |
191 | // Sum weighted.
192 | ΣxA += eachCentroid.x * eachPolygon.area;
193 | ΣyA += eachCentroid.y * eachPolygon.area;
194 | ΣA += eachPolygon.area;
195 | }
196 |
197 | // "Remove" area.
198 | float x = ΣxA / ΣA;
199 | float y = ΣyA / ΣA;
200 |
201 | return new Vector2(x, y);
202 | }
203 |
204 | #endregion
205 |
206 |
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # eppz! `Geometry`
2 | > part of [**Unity.Library.eppz**](https://github.com/eppz/Unity.Library.eppz)
3 |
4 | **📐 2D geometry for Unity.** Suited for everyday polygon hassle.
5 |
6 | Polygon clipping, polygon winding direction, polygon area, polygon centroid, centroid of multiple polygons, line intersection, point-line distance, segment intersection, polygon-point containment, polygon triangulation, polygon Voronoi diagram, polygon offset, polygon outline, polygon buffer, polygon union, polygon substraction, polygon boolean operations, and more.
7 |
8 | 
9 |
10 | The library is **being used in production**. However, it comes with the disclaimed liability and warranty of [MIT License](https://en.wikipedia.org/wiki/MIT_License).
11 |
12 | ## Examples
13 |
14 | If you prefer to read example code immediately, you can find example scenes in [`Scenes`](Scenes) folder.
15 |
16 | + [Polygon-Point containment](Scenes/README.md/#0-polygon-point-containment)
17 | + [Polygon-Segment intersection test](Scenes/README.md/#1-polygon-segment-intersection)
18 | + [Polygon permiter-Point containment (Precise)](Scenes/README.md/#2-polygon-permiter-point-containment-precise)
19 | + [Polygon permiter-Point containment (Default)](Scenes/README.md/#3-polygon-permiter-point-containment-default)
20 | + [Polygon-Segment containment](Scenes/README.md/#4-polygon-segment-containment)
21 | + [Polygon-Polygon containment](Scenes/README.md/#5-polygon-polygon-containment)
22 | + [Vertex facing](Scenes/README.md/#6-vertex-facing)
23 | + [Polygon area, Polygon winding](Scenes/README.md/#7-polygon-area-polygon-winding)
24 | + [Segment-Segment intersection point](Scenes/README.md/#8-segment-segment-intersection-point)
25 | + [Polygon offset](Scenes/README.md/#9-polygon-offset)
26 | + [Multiple polygon centroid](Scenes/README.md/#10-multiple-polygon-centroid)
27 | + [Polygon triangulation](Scenes/README.md/#11-polygon-triangulation)
28 |
29 | ## Model classes
30 |
31 | * [`Vertex.cs`](Model/Vertex.cs)
32 | + Basically a `Vector2` point, but is aware of the polygon context it resides (neighbours, segments, edges, polygon, bisector, normal).
33 | * [`Segment.cs`](Model/Segment.cs)
34 | + Segment of two `Vector2` point. Carries out basic geometry features (point distance, point containment, segment intersection).
35 | * [`Edge.cs`](Model/Edge.cs)
36 | + Edge of two `Vertex` in a polygon (a special `Segment` subclass). Likewise vertices, this model is also aware of the polygon context it resides (neighbours, segments, edges, polygon, perpendicular, normal).
37 | * [`Polygon.cs`](Model/Edge.cs)
38 | + The role player, it really **embodies mostly every feature of this library**. Basically a polygon made of vertices.
39 | + Can be created with point array, transforms, [`Source.Polygon`](Source/Polygon.cs) components. Further polygons can be embedded into recursively. Vertices, edges, polygons can be enumerated (recursively).
40 | + Area, winding direction, centroid are being calculated. Also carries the basic geometry features (point containment, line-, segment-, polygon intersection and more).
41 | + Using library modules, it implements polygon offset (outline), union polygon (polygon clipping), basic mesh triangulation. It implements conversion to both [Clipper](https://github.com/eppz/Clipper) and [Triangle.NET](https://github.com/eppz/Triangle.NET), so you can implement further integration with those (awesome) libraries.
42 |
43 | ## [`Geometry.cs`](Geometry.cs)
44 |
45 | Most of the basic 2D geometry algorithm collection is implemented in this static base class. You can (mostly) **use them with Unity `Vector2` types directly**, so (almost entirely) without the model classes introduced above.
46 |
47 | * **Point**
48 | + [**`ArePointsEqualWithAccuracy()`**](Geometry.cs#L24)
49 | + Determine if points are equal with a given accuracy.
50 | + [**`ArePointsCCW()`**](Geometry.cs#L30)
51 | + Determine winding direction of three points.
52 | * **Rect / Bounds**
53 | + [**`IsRectContainsRectSizeWithAccuracy()`**](Geometry.cs#L41)
54 | + Determine if `rect2.size` fits into `rect1` (compare sizes only).
55 | + [**`IsRectContainsRectWithAccuracy()`**](Geometry.cs#L56)
56 | + Determine if `rect2` is contained by `rect1` (even if permiters are touching) with a given accuracy.
57 | * **Line**
58 | + [**`IntersectionPointOfLines()`**](Geometry.cs#L78)
59 | + Returns intersection point of two lines (defined by segment endpoints). Returns zero, when segments have common points, or when a segment point lies on other.
60 | + [**`PointDistanceFromLine()`**](Geometry.cs#L97)
61 | + Determine point distance from line (defined by segment endpoints).
62 | * **Segment**
63 | + [**`PointIsLeftOfSegment()`**](Geometry.cs#L109)
64 | + Determine if a given point lies on the left side of a segment (line beneath).
65 | + [**`AreSegmentsEqualWithAccuracy()`**](Geometry.cs#L116)
66 | + Determine if segments (defined by endpoints) are equal with a given accuracy.
67 | + [**`HaveSegmentsCommonPointsWithAccuracy()`**](Geometry.cs#L125)
68 | + Determine if segments (defined by endpoints) have common points with a given accuracy.
69 | + [**`AreSegmentsIntersecting()`**](Geometry.cs#L141)
70 | + Determine if two segments defined by endpoints are intersecting (defined by points). True when the two segments are intersecting. Not true when endpoints are equal, nor when a point is contained by other segment. Credits to [Bryce Boe](https://github.com/bboe) (@bboe) for his writeup [Line Segment Intersection Algorithm](http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm).
71 | * **Polygon** (using `EPPZ.Geometry.Polygon`)
72 | + [**`IsPolygonContainsPoint()`**](Geometry.cs#L159)
73 | + Test if a polygon contains the given point (checks for sub-polygons recursive). Uses the same Bryce boe algorithm above, so considerations are the same. See [Point in polygon](https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm) for more.
74 | + [**`CentroidOfPolygons()`**](Geometry.cs#L177)
75 | + Returns the compound centroid of multiple polygon using [Geometric decomposition](https://en.wikipedia.org/wiki/Centroid#By_geometric_decomposition).
76 |
77 | ## Modules
78 |
79 | For clipping, offsetting, triangulating the library use these brilliant third party `C#` libraries below.
80 |
81 | * [Clipper](https://github.com/eppz/Clipper)
82 |
83 | + Polygon and line clipping and offsetting library (C++, C#, Delphi) by Angus Johnson. See standalone project repository [Clipper](https://github.com/eppz/Clipper) for details.
84 |
85 | * [Triangle.NET](https://github.com/eppz/Triangle.NET)
86 |
87 | + Triangle.NET generates 2D (constrained) Delaunay triangulations and high-quality meshes of point sets or planar straight line graphs. It is a C# port by Christian Woltering of Jonathan Shewchuk's Triangle software. See standalone project repository [Triangle.NET](https://github.com/eppz/Triangle.NET) for details.
88 |
89 | ## Naming
90 |
91 | The library uses namespaces heavily. I like to **name things as they are**. An edge in this library called `Edge`, a polygon is called `Polygon`. If it is a polygon model, it resides the `Model` namespace (`EPPZ.Geometry.Model` actually). Whether it is a source component for polygon, it resides in the `Source` namespace. It becomes nicely readable, as you declare polygons like `Model.Polygon`, or reference polygon sources as `Source.Polygon`.
92 |
93 | > In addition, every class is **namespaced in the folder** it resides. If you look at a folder name, you can tell that classes are namespaced to the same as the folder name.
94 |
95 | ## Add-ons
96 |
97 | * [`ClipperAddOns`](AddOns/ClipperAddOns.cs)
98 |
99 | + Mainly `Polygon` extensions for easy conversion between **eppz! Geometry** and [Clipper](https://github.com/eppz/Clipper). It has a method to convert from generic `Vector2[]` array. **[Clipper](https://github.com/eppz/Clipper) works with integers**. So conversion involves a scale up (and a scale down), thus you'll need to pass a scale value to Clipper. (for example **eppz! Geometry** internals use `10e+5f` by default).
100 | + `Polygon PolygonFromClipperPaths(Paths paths, float scale)`
101 | + `Polygon PolygonFromClipperPath(Path path, float scale)`
102 | + `Paths ClipperPaths(this Polygon this_, float scale)`
103 | + `Path ClipperPath(this Polygon this_, float scale)`
104 | + `Vector2[] PointsFromClipperPath(Path path, float scale)`
105 |
106 | * [`TriangleNetAddOns`](AddOns/TriangleNetAddOns.cs)
107 |
108 | + Bridges the gap between library `Model.Polygon` objects and `Triangle.NET` models (meshes, voronoi diagrams).
109 | + `TriangleNet.Geometry.Polygon TriangleNetPolygon(this Polygon this_)`
110 | + `Rect Bounds(this TriangleNet.Voronoi.Legacy.SimpleVoronoi this_)`
111 | + `Paths ClipperPathsFromVoronoiRegions(List voronoiRegions, float scale = 1.0f)`
112 | + `Vector2 VectorFromPoint(TriangleNet.Geometry.Point point)`
113 | + `Vector2[] PointsFromVertices(ICollection vertices)`
114 |
115 | * [`UnityEngineAddOns`](AddOns/UnityEngineAddOns.cs)
116 |
117 | + Contains a single `Model.Polygon` (yet enormously useful) extension that triangulates the corresponding polygon, and hooks up the result into a `UnityEngine.MeshFilter` component. This is the core functionality embedded into `Source.Mesh` component (see example scene [Polygon triangulation](Scenes/README.md/#11-polygon-triangulation) for more).
118 | + `UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, string name = "")`
119 | + `UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, TriangulatorType triangulator, string name = "")`
120 | + `UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, Color color, TriangulatorType triangulator, string name = "")`
121 |
122 | ## License
123 |
124 | > Licensed under the [**MIT License**](https://en.wikipedia.org/wiki/MIT_License).
125 |
--------------------------------------------------------------------------------
/Scenes/README.md:
--------------------------------------------------------------------------------
1 | # [eppz! `Geometry`](https://github.com/eppz/Unity.Library.eppz,Geometry)
2 | > part of [**Unity.Library.eppz**](https://github.com/eppz/Unity.Library.eppz)
3 |
4 | ## Test scenes
5 |
6 | + [Polygon-Point containment](#0-polygon-point-containment)
7 | + [Polygon-Segment intersection test](#1-polygon-segment-intersection)
8 | + [Polygon permiter-Point containment (Precise)](#2-polygon-permiter-point-containment-precise)
9 | + [Polygon permiter-Point containment (Default)](#3-polygon-permiter-point-containment-default)
10 | + [Polygon-Segment containment](#4-polygon-segment-containment)
11 | + [Polygon-Polygon containment](#5-polygon-polygon-containment)
12 | + [Vertex facing](#6-vertex-facing)
13 | + [Polygon area, Polygon winding](#7-polygon-area-polygon-winding)
14 | + [Segment-Segment intersection point](#8-segment-segment-intersection-point)
15 | + [Polygon offset](#9-polygon-offset)
16 | + [Multiple polygon centroid](#10-multiple-polygon-centroid)
17 | + [Polygon triangulation](#11-polygon-triangulation)
18 |
19 | 
20 |
21 | These test scenes are designed to experience / proof the **eppz! Geometry** library features. Hit play, then manipulate the geometry in Scene window while in game mode (watch out to move the points directly instead their parent container). Every relevant code is in the corresponding `Controller_#.cs`, so you can see **how to use the API**.
22 |
23 | You can define a polygon with simple `Vector2[]` array, but for sake of simplicity, test scenes uses some **polygon sourcing helper classes** ([`Components.PolygonSource`](../Components/PolygonSource.cs)) those take simple `GameObject` transforms as input. They also keep the polygon models updated on `GameObject` changes.
24 |
25 | Another helper objects are **polygon line renderers** ([`Lines.PolygonLineRenderer`](../Lines/PolygonLineRenderer.cs)). These renderers are [`DirectLineRenderer`](https://github.com/eppz/Unity.Library.eppz.Lines/blob/master/DirectLineRenderer.cs) using fellow library [eppz! Lines](https://github.com/eppz/Unity.Library.eppz.Lines).
26 |
27 | Beside these helper classes, you can easily construct `Polygon` / `Segment` instances using simple `Vector2` inputs as well. Having these test scenes, you can easily provision the mechanism of each geometry feature even with your own polygons.
28 |
29 | ## 0. Polygon-Point containment
30 |
31 | The star polygon drawn yellow when it contains all three points.
32 |
33 | + When points appear to be on a polygon edge, test will return false
34 | + When point is at a polygon vertex, test will return false
35 |
36 | ```C#
37 | bool test = polygon.ContainsPoint(point);
38 | ```
39 | See [`Controller_0.cs`](Controllers/Controller_0.cs) for the full script context.
40 |
41 | ## 1. Polygon-Segment intersection
42 |
43 | The star polygon drawn yellow when any of the two segments intersects any polygon edge.
44 |
45 | + Returns false when a segment endpoint appears to be on a polygon edge
46 | + Returns false when a segment endpoint is at a polygon vertex
47 |
48 | ```C#
49 | bool test = polygon.IsIntersectingWithSegment(segment);
50 | ```
51 | See [`Controller_1.cs`](Controllers/Controller_1.cs) for the full script context.
52 |
53 | ## 2. Polygon permiter-Point containment (Precise)
54 |
55 | The star polygon drawn yellow when the point is contained by the polygon permiter. Accuracy means the line width of the polygon permiter (is `1.0f` by default).
56 |
57 | + Returns true even if the point appears to be on a polygon edge
58 | + Returns true even if the point is at a polygon vertex
59 |
60 | ```C#
61 | bool test = polygon.PermiterContainsPoint(point, accuracy, Segment.ContainmentMethod.Precise);
62 | ```
63 | See [`Controller_2.cs`](Controllers/Controller_2.cs) for the full script context.
64 |
65 | **Points contained by a segment** (even edge or polygon permiter) should be calculated with a given **accuracy**. This accuracy is set to `1e-6f` by default, but **can be set to any value** per each containment test (like above).
66 |
67 | Point containment tests has two **containment method**, `ContainmentMethod.Default` and `ContainmentMethod.Precise`. The former is less computation intensive than the latter. Depending on your ue case, you may trade precision over performance. The figure below summarizes the dissimilarities of the two method.
68 |
69 | 
70 |
71 | ## 3. Polygon permiter-Point containment (Default)
72 |
73 | Actually the same as before, but a smaller accuracy is given (`0.1f`). The star polygon drawn yellow when the point appears to be on any polygon edge of at a polygon vertex.
74 |
75 | + Returns true even if the point appears to be on a polygon edge
76 | + Returns true even if the point is at a polygon vertex
77 |
78 | ```C#
79 | float accuracy = 0.1f;
80 | bool test = polygon.PermiterContainsPoint(point, accuracy);
81 | ```
82 | See [`Controller_3.cs`](Controllers/Controller_3.cs) for the full script context.
83 |
84 | ## 4. Polygon-Segment containment
85 |
86 | The star drawn yellow when it contains both edge. This is a compund test of polygon-point containment, polygon permiter-point containment, polygon-segment intersection.
87 |
88 | + Returns true even if the point appears to be on a polygon edge (thanks to permiter test)
89 | + Returns true even if the point is at a polygon vertex (thanks to permiter test)
90 |
91 | See [`Controller_4.cs`](Controllers/Controller_4.cs) for the full script context.
92 |
93 | ## 5. Polygon-Polygon containment
94 |
95 | The star drawn yellow when it contain the rectangular polygon. This is also a compund test of polygon-point containment, polygon-segment intersection, polygon permiter-point containment.
96 |
97 | A polygon contains another polygon, when
98 | + other polygon vertices are contained by polygon
99 | + other polygon segments are not intersecting with polygon
100 | + other polygon vertices are not contained by polygon permiter
101 |
102 | See [`Controller_5.cs`](Controllers/Controller_5.cs) for the full script context.
103 |
104 | ## 6. Vertex facing
105 |
106 | The segments in ths example can think of imaginary polygon edges. The corner vertex normal segment drawn yellow when it faces inward the imaginary polygon, drawn white when facing outward.
107 |
108 | It uses `Segment.IsPointLeft()` to create a compund test with both segments. It full calculation goes like below.
109 |
110 | The two segments encompasses an acute angle if
111 | + the endpoint of the second segment lies on the left of the first segment
112 |
113 | The vertex normal facing outward if
114 | + the neighbouring segment encompasses an acute angle
115 | + and the normal point lies on the left of both segments
116 | + or the neighbouring segments encompass an obtuse angle
117 | + and the normal point lies on the left of one of the segments
118 |
119 | See [`Controller_6.cs`](Controllers/Controller_6.cs) for the full script context.
120 |
121 | ## 7. Polygon area, Polygon winding
122 |
123 | The winding direction of a polygon comes to a good use when you want to validate the result of further polygon operations. The `winding` property of each `Polygon` instance gets calculated at construction time, and each time its topology gets updated (using `UpdatePointPositionsWithSource()`, `UpdatePointPositionsWithTransforms()`, `Scale()`, `Translate()`), or you can invoke `Calculate()` directly if you manipulated underlying point models directly.
124 |
125 | In this scene you can see how area and winding of a polygon gets calculated. Just hit play and nudge some points around.
126 |
127 | ```C#
128 | // After a polygon constructed, you can simply access values.
129 | float area = polygon.area;
130 | bool isCW = polygon.isCW;
131 | ```
132 |
133 | See [`Model/Polygon.cs`](Model/Polygon.cs) source for the details.
134 |
135 | ## 8. Segment-Segment intersection point
136 |
137 | Segment intersection has two parts actually. Get the **intersection point of the lines** defined by the segment, then look up if the point **resides on the segments**.
138 |
139 | The first part has implemented as a generic `Geometry.IntersectionOfSegments()`.
140 |
141 | The second part gets more tricky, uses `accuracy` like many tests above. Checks if bounds are overlap, after that it uses the segment-point containment for the endpoints, then checks if the segments has intersection point at all (using winding tests), then returns with the intersection point of lines.
142 |
143 | > To avoid redundant test method calls, the method follows API style of `Physics.Raycast`, where you can query if there is intersection at all, then use point only if any.
144 |
145 | ```C#
146 | // Output will have non-zero value only on having a valid intersection.
147 | Vector2 intersectionPoint;
148 | bool isIntersecting = a.IntersectionWithSegment(b, out intersectionPoint);
149 | ```
150 |
151 | See [`Controller_8.cs`](Controllers/Controller_8.cs) for the full script context.
152 |
153 | ## 9. Polygon offset
154 |
155 | Robust polygon offset (also known as polygon outline / polygon buffer) solution (using [Clipper](https://github.com/eppz/Clipper) by Angus Johnson).
156 |
157 | ```C#
158 | float offset = 0.2f;
159 | Polygon offsetPolygon = polygon.OffsetPolygon(offset);
160 | ```
161 |
162 | See [`Controller_9.cs`](Controllers/Controller_9.cs) for the full script context.
163 |
164 | ## 10. Multiple polygon centroid
165 |
166 | You can see how the compound centorid changes as you nudge polygons, vertices around. Algorithm uses [Geometric decomposition](https://en.wikipedia.org/wiki/Centroid#By_geometric_decomposition).
167 |
168 | ```C#
169 | // Calculate compund centroid.
170 | centroid.position = Geometry.CentroidOfPolygons(polygons));
171 | ```
172 | See [`Controller_10.cs`](Controllers/Controller_10.cs) for the full script context.
173 |
174 | ## 11. Polygon triangulation
175 |
176 | This scene uses a `Source.Mesh` component to simply **triangluate a polygon**. If both `Source.Polygon` and `UnityEngine.MeshFilter` component is present on a `GameObject`, you can use this setup. It uses an extension method `Polygon.Mesh()` that hooks up `Triangle.NET` mesh output into a `UnityEngine.MeshFilter` (with some additional issue resolved regarding self intersecting polygons).
177 |
178 | ```C#
179 | // Assign trianglated mesh.
180 | meshFilter.mesh = polygon.Mesh(color, triangulator);
181 | ```
182 | See [`Source/Mesh.cs`](Source/Mesh.cs) source for the details.
183 |
184 | ## License
185 |
186 | > Licensed under the [**MIT License**](https://en.wikipedia.org/wiki/MIT_License).
--------------------------------------------------------------------------------
/Model/Segment.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 |
12 |
13 | namespace EPPZ.Geometry.Model
14 | {
15 |
16 |
17 | public class Segment
18 | {
19 |
20 |
21 | static public float defaultAccuracy = 1e-6f;
22 |
23 | public enum ContainmentMethod { Default, Precise }
24 | static public ContainmentMethod defaultContainmentMethod = ContainmentMethod.Default;
25 |
26 | private Vector2 _a;
27 | public virtual Vector2 a
28 | {
29 | get { return _a; }
30 | set { _a = value; }
31 | }
32 | private Vector2 _b;
33 | public virtual Vector2 b
34 | {
35 | get { return _b; }
36 | set { _b = value; }
37 | }
38 |
39 | #region Calculations
40 |
41 | // If `alwaysCalculate` is on, every `normal` and `perpendicular` property access invokes recalculation of values based on actual topology.
42 | public bool alwaysCalculate = true;
43 |
44 | private Vector2 _normal;
45 | public Vector2 normal
46 | {
47 | get
48 | {
49 | if (_normal == Vector2.zero || alwaysCalculate) { CalculateNormal(); } // Lazy calculation or force calculate on every access
50 | return _normal;
51 | }
52 |
53 | set
54 | { _normal = value; }
55 | }
56 |
57 | public Vector2 _perpendicular;
58 | public Vector2 perpendicular
59 | {
60 | get
61 | {
62 | if (_perpendicular == Vector2.zero || alwaysCalculate) { CalculatePerpendicular(); } // Lazy calculation or force calculate on every access
63 | return _perpendicular;
64 | }
65 |
66 | set
67 | { _perpendicular = value; }
68 | }
69 |
70 | public void CalculateNormal()
71 | {
72 | _normal = this.perpendicular.normalized;
73 | }
74 |
75 | public void CalculatePerpendicular()
76 | {
77 | Vector2 translated = (this.b - this.a); // Translate to origin
78 | _perpendicular = new Vector2( -translated.y, translated.x); // Rotate CCW
79 | }
80 |
81 | #endregion
82 |
83 |
84 | #region Factories
85 |
86 | public static Segment SegmentWithSource(Source.Segment segmentSource)
87 | {
88 | return Segment.SegmentWithPointTransforms(segmentSource.points, segmentSource.coordinates);
89 | }
90 |
91 | public static Segment SegmentWithPointTransforms(Transform[] pointTransforms, Source.Segment.Coordinates coordinates = Source.Segment.Coordinates.World) // Uses Transform.localPosition.xy()
92 | {
93 | if (coordinates == Source.Segment.Coordinates.World)
94 | { return Segment.SegmentWithPoints(pointTransforms[0].position, pointTransforms[1].position); }
95 |
96 | // Source.Segment.Coordinates.Local
97 | return Segment.SegmentWithPoints(pointTransforms[0].localPosition, pointTransforms[1].localPosition);
98 | }
99 |
100 | public static Segment SegmentWithPoints(Vector2 a_, Vector2 b_)
101 | {
102 | Segment instance = new Segment();
103 | instance.a = a_;
104 | instance.b = b_;
105 | return instance;
106 | }
107 |
108 | #endregion
109 |
110 |
111 | #region Model updates
112 |
113 | public void UpdateWithSource(Source.Segment segmentSource) // Assuming unchanged point count
114 | {
115 | UpdateWithTransforms(segmentSource.points, segmentSource.coordinates);
116 | }
117 |
118 | public void UpdateWithTransforms(Transform[] pointTransforms, Source.Segment.Coordinates coordinates = Source.Segment.Coordinates.World) // Assuming unchanged point count
119 | {
120 | if (coordinates == Source.Segment.Coordinates.World)
121 | {
122 | a = pointTransforms[0].position;
123 | b = pointTransforms[1].position;
124 | return;
125 | }
126 |
127 | // Source.Segment.Coordinates.Local
128 | a = pointTransforms[0].localPosition;
129 | b = pointTransforms[1].localPosition;
130 | }
131 |
132 | #endregion
133 |
134 |
135 | #region Accessors
136 |
137 | public Rect bounds // Readonly
138 | {
139 | get
140 | {
141 | Rect bounds_ = new Rect();
142 |
143 | // Set bounds.
144 | bounds_.xMin = Mathf.Min(a.x, b.x);
145 | bounds_.xMax = Mathf.Max(a.x, b.x);
146 | bounds_.yMin = Mathf.Min(a.y, b.y);
147 | bounds_.yMax = Mathf.Max(a.y, b.y);
148 |
149 | return bounds_;
150 | }
151 | }
152 |
153 | public Rect ExpandedBounds(float accuracy)
154 | {
155 | float treshold = accuracy / 2.0f;
156 | Rect bounds_ = this.bounds;
157 | return Rect.MinMaxRect(
158 | bounds_.xMin - treshold,
159 | bounds_.yMin - treshold,
160 | bounds_.xMax + treshold,
161 | bounds_.yMax + treshold);
162 | }
163 |
164 | public bool ContainsPoint(Vector2 point)
165 | { return ContainsPoint(point, defaultAccuracy); }
166 |
167 | public bool ContainsPoint(Vector2 point, float accuracy)
168 | { return ContainsPoint(point, accuracy, ContainmentMethod.Default); }
169 |
170 | public bool IsPointLeft(Vector2 point)
171 | { return Geometry.PointIsLeftOfSegment(point, this.a, this.b); }
172 |
173 | public bool ContainsPoint(Vector2 point, float accuracy, ContainmentMethod containmentMethod)
174 | {
175 | float treshold = accuracy / 2.0f;
176 |
177 | // Expanded bounds containment test.
178 | Rect expandedBounds = this.ExpandedBounds(accuracy);
179 | bool expandedBoundsContainment = expandedBounds.Contains(point);
180 | if (expandedBoundsContainment == false) return false; // Only if passed
181 |
182 | // Line distance test.
183 | float distance = this.DistanceToPoint(point);
184 | bool lineDistanceTest = distance < treshold;
185 | if (lineDistanceTest == false) return false; // Only if passed
186 |
187 | if (containmentMethod == ContainmentMethod.Precise)
188 | {
189 | // Perpendicular segment.
190 | Vector2 normalizedHalf = (this.b - this.a) / 2.0f;
191 | float halfLength = normalizedHalf.magnitude;
192 | Vector2 normalizedHalfPerpendicular = new Vector2( -normalizedHalf.y, normalizedHalf.x );
193 | Vector2 perpendicular_a = this.a + normalizedHalf;
194 | Vector2 perpendicular_b = this.a + normalizedHalf + normalizedHalfPerpendicular;
195 |
196 | // Perpendicular line distance test.
197 | float perpendicularDistance = Geometry.PointDistanceFromLine(point, perpendicular_a, perpendicular_b);
198 | bool perpendicularDistanceTest = perpendicularDistance < halfLength;
199 |
200 | // Endpoint distance test if previous failed.
201 | if (perpendicularDistanceTest == false)
202 | {
203 | float distanceFromEndPoints = Mathf.Min( Vector2.Distance(this.a, point), Vector2.Distance(this.b, point) );
204 | bool endpointDistanceTest = distanceFromEndPoints < treshold;
205 | if (endpointDistanceTest == false) return false; // Only if passed
206 | }
207 | }
208 |
209 | // All passed.
210 | return true;
211 | }
212 |
213 | #endregion
214 |
215 |
216 | #region Geometry features
217 |
218 | ///
219 | /// True when the two segments are intersecting. Not true when endpoints
220 | /// are equal, nor when a point is contained by other segment.
221 | /// Can say this algorithm has infinite precision.
222 | ///
223 | public bool IsIntersectingWithSegment(Segment segment)
224 | {
225 | // No intersecting if bounds don't even overlap (slight optimization).
226 | bool boundsOverlaps = this.bounds.Overlaps(segment.bounds);
227 | if (boundsOverlaps == false) return false;
228 |
229 | // Do the Bryce Boe test.
230 | return Geometry.AreSegmentsIntersecting(this.a, this.b, segment.a, segment.b);
231 | }
232 |
233 | ///
234 | /// Returns intersection when the two segments are intersecting. Not returns anything when endpoints
235 | /// are equal, nor when a point is contained by other segment.
236 | /// Can say this algorithm has infinite precision.
237 | ///
238 | public bool IntersectionWithSegment(Segment segment, out Vector2 intersectionPoint)
239 | { return IntersectionWithSegmentWithAccuracy(segment, 0.0f, out intersectionPoint); }
240 |
241 | public bool IntersectionWithSegmentWithAccuracy(Segment segment, float accuracy, out Vector2 intersectionPoint)
242 | { return IntersectionWithSegmentWithAccuracy(segment, accuracy, defaultContainmentMethod, out intersectionPoint); }
243 |
244 | public bool IntersectionWithSegmentWithAccuracy(Segment segment, ContainmentMethod containmentMethod, out Vector2 intersectionPoint)
245 | { return IntersectionWithSegmentWithAccuracy(segment, defaultAccuracy, containmentMethod, out intersectionPoint); }
246 |
247 | public bool IntersectionWithSegmentWithAccuracy(Segment segment, float accuracy, ContainmentMethod containmentMethod, out Vector2 intersectionPoint)
248 | {
249 | intersectionPoint = Vector2.zero; // Default
250 |
251 | // No intersecting if bounds don't even overlap.
252 | Rect expandedBounds = this.ExpandedBounds(accuracy);
253 | Rect otherExpandedBounds = segment.ExpandedBounds(accuracy);
254 | bool boundsOverlaps = expandedBounds.Overlaps(otherExpandedBounds);
255 | if (boundsOverlaps == false)
256 | {
257 | return false; // No intersection
258 | }
259 |
260 | if (accuracy > 0.0f) // Only any accuracy is given
261 | {
262 | // Look up point containments.
263 | bool containsA = this.ContainsPoint (segment.a, accuracy, containmentMethod);
264 | if (containsA)
265 | {
266 | intersectionPoint = segment.a;
267 | return true; // Intersecting
268 | }
269 |
270 | bool containsB = this.ContainsPoint (segment.b, accuracy, containmentMethod);
271 | if (containsB)
272 | {
273 | intersectionPoint = segment.b;
274 | return true; // Intersecting
275 | }
276 |
277 | bool otherContainsA = segment.ContainsPoint (this.a, accuracy, containmentMethod);
278 | if (otherContainsA)
279 | {
280 | intersectionPoint = this.a;
281 | return true; // Intersecting
282 | }
283 |
284 | bool otherContainsB = segment.ContainsPoint (this.b, accuracy, containmentMethod);
285 | if (otherContainsB)
286 | {
287 | intersectionPoint = this.b;
288 | return true; // Intersecting
289 | }
290 | }
291 |
292 | // Do the Bryce Boe test.
293 | bool isIntersecting = Geometry.AreSegmentsIntersecting(this.a, this.b, segment.a, segment.b);
294 | if (isIntersecting == false)
295 | {
296 | return false; // No intersection
297 | }
298 |
299 | // All fine, intersection point can be determined.
300 | intersectionPoint = Geometry.IntersectionPointOfLines(this.a, this.b, segment.a, segment.b); // Actually the intersection of lines defined by segments
301 | return true; // Intersecting
302 | }
303 |
304 | public float DistanceToPoint(Vector2 point_)
305 | {
306 | return Geometry.PointDistanceFromLine(point_, this.a, this.b);
307 | }
308 |
309 | #endregion
310 |
311 |
312 | }
313 | }
--------------------------------------------------------------------------------
/Model/Polygon.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 Geri Borbás http://www.twitter.com/_eppz
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 | //
8 | using UnityEngine;
9 | using System;
10 | using System.Collections;
11 | using System.Collections.Generic;
12 | using System.Linq;
13 |
14 |
15 | namespace EPPZ.Geometry.Model
16 | {
17 |
18 |
19 | using ClipperLib;
20 | using Path = List;
21 | using Paths = List>;
22 |
23 |
24 | public class Polygon
25 | {
26 |
27 |
28 | // Identifiers.
29 | public int index;
30 | public string name;
31 |
32 | // Windings.
33 | public bool isCW { get { return (Mathf.Sign(_area) < 0.0f); } }
34 | public bool isCCW { get { return (Mathf.Sign(_area) > 0.0f); } }
35 | public enum Winding { CCW, CW };
36 | public Winding winding { get { return (isCCW) ? Winding.CCW : Winding.CW; } }
37 |
38 | ///
39 | /// For internal use.
40 | /// Edge, Vertex class can read from this directly
41 | /// Debug renderers can access raw points during development
42 | /// From the outside, use vertices, edges only, or enumerators
43 | ///
44 | private Vector2[] _points;
45 | public Vector2[] points { get { return _points; } } // Readonly
46 |
47 | public Vertex[] vertices; // Vertices of this polygon (excluding sub polygon vertices)
48 | public Edge[] edges; // Edges of this polygon (excluding sub polygon edges)
49 | private List polygons = new List(); // Sub-polygons (if any)
50 |
51 | private Rect _bounds = new Rect();
52 | public Rect bounds { get { return _bounds; } }
53 |
54 | private float _area = 0.0f;
55 | public float area { get { return _area; } }
56 |
57 | // Yet for single polygons only (see centroid of compound polygons).
58 | private Vector2 _centroid;
59 | public Vector2 centroid { get { return _centroid; } }
60 |
61 |
62 | #region Factories
63 |
64 | public static Polygon PolygonWithPointList(List pointList)
65 | { return Polygon.PolygonWithPoints(pointList.ToArray()); }
66 |
67 | public static Polygon PolygonWithSource(Source.Polygon polygonSource)
68 | {
69 | Polygon rootPolygon = Polygon.PolygonWithPointTransforms(polygonSource.points, polygonSource.coordinates);
70 |
71 | // Collect sub-polygons if any.
72 | foreach (Transform eachChildTransform in polygonSource.gameObject.transform)
73 | {
74 | GameObject eachChildGameObject = eachChildTransform.gameObject;
75 | Source.Polygon eachChildPolygonSource = eachChildGameObject.GetComponent();
76 | if (eachChildPolygonSource != null)
77 | {
78 | Polygon eachSubPolygon = Polygon.PolygonWithSource(eachChildPolygonSource);
79 | rootPolygon.AddPolygon(eachSubPolygon);
80 | }
81 | }
82 |
83 | return rootPolygon;
84 | }
85 |
86 | public Polygon Copy()
87 | { return Polygon.PolygonWithPolygon(this); }
88 |
89 | public static Polygon PolygonWithPolygon(Polygon polygon)
90 | {
91 | Polygon rootPolygon = null;
92 |
93 | // Compose with sub-olygons (if any).
94 | polygon.EnumeratePolygons((Polygon eachPolygon) =>
95 | {
96 | if (rootPolygon == null)
97 | { rootPolygon = Polygon.PolygonWithPoints(eachPolygon.points); }
98 | else
99 | { rootPolygon.AddPolygon(Polygon.PolygonWithPoints(eachPolygon.points)); }
100 | });
101 |
102 | return rootPolygon;
103 | }
104 |
105 | public static Polygon PolygonWithPointTransforms(Transform[] pointTransforms, Source.Polygon.Coordinates coordinates)
106 | {
107 | // Create points array.
108 | Vector2[] points = new Vector2[pointTransforms.Length];
109 | for (int index = 0; index < pointTransforms.Length; index++)
110 | {
111 | Transform eachPointTransform = pointTransforms[index];
112 |
113 | if (coordinates == Source.Polygon.Coordinates.World)
114 | { points[index] = eachPointTransform.position.xy(); }
115 |
116 | if (coordinates == Source.Polygon.Coordinates.Local)
117 | { points[index] = eachPointTransform.localPosition.xy(); }
118 | }
119 |
120 | return Polygon.PolygonWithPoints(points);
121 | }
122 |
123 | public static Polygon PolygonWithPoints(Vector2[] points)
124 | { return PolygonWithPoints(points, 0.0f); }
125 |
126 | public static Polygon PolygonWithPoints(Vector2[] points, float angle)
127 | {
128 | Polygon polygon = new Polygon(points.Length);
129 |
130 | // Create points (copy actually).
131 | for (int index = 0; index < points.Length; index++)
132 | {
133 | if (angle == 0.0f)
134 | { polygon._points[index] = points[index]; }
135 | else
136 | { polygon._points[index] = points[index].Rotated(angle); }
137 | }
138 |
139 | // Polygon calculations.
140 | polygon.Calculate();
141 |
142 | // Create members.
143 | polygon.CreateVerticesFromPoints();
144 | polygon.CreateEdgesConnectingPoints();
145 |
146 | return polygon;
147 | }
148 |
149 | public Polygon(int pointCount = 1)
150 | {
151 | this._points = new Vector2[pointCount];
152 | this.vertices = new Vertex[pointCount];
153 | this.edges = new Edge[pointCount];
154 | }
155 |
156 | #endregion
157 |
158 |
159 | #region Model updates
160 |
161 | public void UpdatePointPositionsWithSource(Source.Polygon polygonSource) // Assuming unchanged point count
162 | {
163 | UpdatePointPositionsWithTransforms(polygonSource.points, polygonSource.coordinates);
164 |
165 | // Update sub-polygons if any.
166 | foreach (Transform eachChildTransform in polygonSource.gameObject.transform)
167 | {
168 | GameObject eachChildGameObject = eachChildTransform.gameObject;
169 | Source.Polygon eachChildPolygonSource = eachChildGameObject.GetComponent();
170 | if (eachChildPolygonSource != null)
171 | {
172 | eachChildPolygonSource.polygon.UpdatePointPositionsWithTransforms(eachChildPolygonSource.points, eachChildPolygonSource.coordinates);
173 | }
174 | }
175 | }
176 |
177 | public void UpdatePointPositionsWithTransforms(Transform[] pointTransforms, Source.Polygon.Coordinates coordinates) // Assuming unchanged point count
178 | {
179 | for (int index = 0; index < pointTransforms.Length; index++)
180 | {
181 | Transform eachPointTransform = pointTransforms[index];
182 |
183 | if (coordinates == Source.Polygon.Coordinates.World)
184 | { _points[index] = eachPointTransform.position.xy(); }
185 |
186 | if (coordinates == Source.Polygon.Coordinates.Local)
187 | { _points[index] = eachPointTransform.localPosition.xy(); }
188 | }
189 |
190 | // Polygon calculations.
191 | Calculate();
192 | }
193 |
194 | public void AddPolygon(Polygon polygon)
195 | {
196 | polygons.Add(polygon);
197 |
198 | // Polygon calculations.
199 | Calculate();
200 | }
201 |
202 | #endregion
203 |
204 |
205 | #region Accessors
206 |
207 | public int pointCount { get { return _points.Length; } } // Readonly
208 | public int vertexCount { get { return vertices.Length; } } // Readonly
209 | public int edgeCount { get { return edges.Length; } } // Readonly
210 | public int polygonCount { get { return polygons.Count; } } // Readonly
211 | public int pointCountRecursive
212 | {
213 | get
214 | {
215 | int pointCountRecursive = pointCount;
216 | foreach (Polygon eachPolygon in polygons)
217 | {
218 | pointCountRecursive += eachPolygon.pointCount;
219 | }
220 | return pointCountRecursive;
221 | }
222 | }
223 |
224 | #endregion
225 |
226 |
227 | #region Enumerators
228 |
229 | public void EnumeratePoints(Action action)
230 | {
231 | // Enumerate local points.
232 | foreach (Vector2 eachPoint in _points)
233 | {
234 | action(eachPoint);
235 | }
236 | }
237 |
238 | public void EnumerateVertices(Action action)
239 | {
240 | // Enumerate local points.
241 | foreach (Vertex eachVertex in vertices)
242 | {
243 | action(eachVertex);
244 | }
245 | }
246 |
247 | public void EnumerateEdges(Action action)
248 | {
249 | // Enumerate local points.
250 | foreach (Edge eachEdge in edges)
251 | {
252 | action(eachEdge);
253 | }
254 | }
255 |
256 | public void EnumeratePointsRecursive(Action action)
257 | {
258 | // Enumerate local points.
259 | foreach (Vector2 eachPoint in _points)
260 | {
261 | action(eachPoint);
262 | }
263 |
264 | // Enumerate each sub-polygon points.
265 | foreach (Polygon eachPolygon in polygons)
266 | {
267 | eachPolygon.EnumeratePointsRecursive((Vector2 eachPoint_) =>
268 | {
269 | action(eachPoint_);
270 | });
271 | }
272 | }
273 |
274 | public void EnumerateVerticesRecursive(Action action)
275 | {
276 | // Enumerate local points.
277 | foreach (Vertex eachVertex in vertices)
278 | {
279 | action(eachVertex);
280 | }
281 |
282 | // Enumerate each sub-polygon points.
283 | foreach (Polygon eachPolygon in polygons)
284 | {
285 | eachPolygon.EnumerateVerticesRecursive((Vertex eachVertex_) =>
286 | {
287 | action(eachVertex_);
288 | });
289 | }
290 | }
291 |
292 | public void EnumerateEdgesRecursive(Action action)
293 | {
294 | // Enumerate local points.
295 | foreach (Edge eachEdge in edges)
296 | {
297 | action(eachEdge);
298 | }
299 |
300 | // Enumerate each sub-polygon points.
301 | foreach (Polygon eachPolygon in polygons)
302 | {
303 | eachPolygon.EnumerateEdgesRecursive((Edge eachEdge_) =>
304 | {
305 | action(eachEdge_);
306 | });
307 | }
308 | }
309 |
310 | public void EnumeratePolygons(Action action)
311 | {
312 | action(this); // Including this (a bit unexpected)
313 |
314 | // Enumerate sub-polygons.
315 | foreach (Polygon eachPolygon in polygons)
316 | {
317 | action(eachPolygon);
318 | }
319 | }
320 |
321 | #endregion
322 |
323 |
324 | #region Polygon calculations
325 |
326 | public void Calculate()
327 | {
328 | _CalculateBounds();
329 | _CalculateArea();
330 | _CalculateCentroid();
331 | }
332 |
333 | void _CalculateBounds()
334 | {
335 | float left = float.MaxValue; // Out in the right
336 | float right = float.MinValue; // Out in the left
337 | float top = float.MinValue; // Out in the bottom
338 | float bottom = float.MaxValue; // Out in the top
339 |
340 | // Enumerate points.
341 | EnumeratePointsRecursive((Vector2 eachPoint) =>
342 | {
343 | // Track bounds.
344 | if (eachPoint.x < left) left = eachPoint.x; // Seek leftmost
345 | if (eachPoint.x > right) right = eachPoint.x; // Seek rightmost
346 | if (eachPoint.y < bottom) bottom = eachPoint.y; // Seek bottommost
347 | if (eachPoint.y > top) top = eachPoint.y; // Seek topmost
348 | });
349 |
350 | // Set bounds.
351 | _bounds.xMin = left;
352 | _bounds.yMin = bottom;
353 | _bounds.xMax = right;
354 | _bounds.yMax = top;
355 | }
356 |
357 | private void _CalculateArea()
358 | {
359 |
360 | // From https://en.wikipedia.org/wiki/Shoelace_formula
361 | Vector2[] points_ = new Vector2[_points.Length + 1];
362 | System.Array.Copy(_points, points_, _points.Length);
363 | points_[_points.Length] = _points[0];
364 |
365 | // Calculate area.
366 | float firstProducts = 0.0f;
367 | float secondProducts = 0.0f;
368 | for (int index = 0; index < points_.Length - 1; index++)
369 | {
370 | Vector2 eachPoint = points_[index];
371 | Vector2 eachNextPoint = points_[index + 1];
372 |
373 | firstProducts += eachPoint.x * eachNextPoint.y;
374 | secondProducts += eachPoint.y * eachNextPoint.x;
375 | }
376 | _area = (firstProducts - secondProducts) / 2.0f;
377 |
378 | // Add / Subtract sub-polygon areas.
379 | foreach (Polygon eachPolygon in polygons)
380 | {
381 | // Outer or inner polygon (supposing there is no self-intersection).
382 | _area += eachPolygon.area;
383 | }
384 | }
385 |
386 | private void _CalculateCentroid()
387 | {
388 | // Enumerate points.
389 | float Σx = 0.0f;
390 | float Σy = 0.0f;
391 | EnumeratePoints((Vector2 eachPoint) =>
392 | {
393 | Σx += eachPoint.x;
394 | Σy += eachPoint.y;
395 | });
396 |
397 | // Average.
398 | float x = Σx / pointCount;
399 | float y = Σy / pointCount;
400 |
401 | // Assign.
402 | _centroid = new Vector2(x, y);
403 | }
404 |
405 | private void CreateVerticesFromPoints()
406 | {
407 | // Enumerate points (only for index).
408 | Vertex eachVertex = null;
409 | Vertex eachPreviousVertex = null;
410 | for (int index = 0; index < _points.Length; index++)
411 | {
412 | eachVertex = Vertex.VertexAtIndexInPolygon(index, this);
413 |
414 | // Inject references.
415 | if (eachPreviousVertex != null)
416 | {
417 | eachPreviousVertex.SetNextVertex(eachVertex);
418 | eachVertex.SetPreviousVertex(eachPreviousVertex);
419 | }
420 |
421 | // Collect.
422 | vertices[index] = eachVertex;
423 |
424 | // Track.
425 | eachPreviousVertex = eachVertex;
426 | }
427 |
428 | // Inject last references.
429 | Vertex firstVertex = vertices[0];
430 | eachVertex.SetNextVertex(firstVertex);
431 | firstVertex.SetPreviousVertex(eachVertex);
432 | }
433 |
434 | void CreateEdgesConnectingPoints()
435 | {
436 | // Enumerate vertices.
437 | Edge eachEdge = null;
438 | Edge eachPreviousEdge = null;
439 | EnumerateVertices((Vertex eachVertex) =>
440 | {
441 | int index = eachVertex.index;
442 | eachEdge = Edge.EdgeAtIndexWithVertices(index, eachVertex, eachVertex.nextVertex);
443 |
444 | // Inject references.
445 | if (eachPreviousEdge != null)
446 | {
447 | eachPreviousEdge.SetNextEdge(eachEdge);
448 | eachEdge.SetPreviousEdge(eachPreviousEdge);
449 | }
450 |
451 | // Collect.
452 | edges[index] = eachEdge;
453 |
454 | // Track.
455 | eachPreviousEdge = eachEdge;
456 | });
457 |
458 | // Inject last references.
459 | Edge firstEdge = edges[0];
460 | eachEdge.SetNextEdge(firstEdge);
461 | firstEdge.SetPreviousEdge(eachEdge);
462 |
463 | // Inject vertex edge references.
464 | EnumerateEdges((Edge eachEdge_) =>
465 | {
466 | eachEdge_.vertexA.SetPreviousEdge(eachEdge_.previousEdge);
467 | eachEdge_.vertexA.SetNextEdge(eachEdge_);
468 | });
469 | }
470 |
471 | #endregion
472 |
473 |
474 | #region Geometry features
475 |
476 | public bool ContainsPoint(Vector2 point)
477 | {
478 | return Geometry.IsPolygonContainsPoint(this, point);
479 | }
480 |
481 | public bool PermiterContainsPoint(Vector2 point)
482 | { return PermiterContainsPoint(point, Segment.defaultAccuracy); }
483 |
484 | public bool PermiterContainsPoint(Vector2 point, float accuracy)
485 | { return PermiterContainsPoint(point, accuracy, Segment.ContainmentMethod.Default); }
486 |
487 | public bool PermiterContainsPoint(Vector2 point, float accuracy, Segment.ContainmentMethod containmentMethod)
488 | {
489 | bool contains = false;
490 | EnumerateEdgesRecursive ((Edge eachEdge) =>
491 | {
492 | contains |= eachEdge.ContainsPoint(point, accuracy, containmentMethod);
493 | });
494 |
495 | return contains;
496 | }
497 |
498 | public bool IsIntersectingWithSegment(Segment segment)
499 | {
500 | bool isIntersecting = false;
501 | EnumerateEdgesRecursive ((Edge eachEdge) =>
502 | {
503 | isIntersecting |= segment.IsIntersectingWithSegment(eachEdge);
504 | });
505 |
506 | return isIntersecting;
507 | }
508 |
509 | #endregion
510 |
511 |
512 | #region Geometry features (Offset)
513 |
514 | // Clipper precision.
515 | public static float clipperScale = 10e+5f;
516 | public static float clipperArcTolerance = 10e+3f; // 2 magnitude smaller
517 |
518 | // Not simplified, nor rounded.
519 | public Polygon OffsetPolygon(float offset)
520 | { return OffsetPolygon(offset, false, false); }
521 |
522 | // Not simplified.
523 | public Polygon RoundedOffsetPolygon(float offset)
524 | { return OffsetPolygon(offset, false, true); }
525 |
526 | // Full featured.
527 | public Polygon SimplifiedAndRoundedOffsetPolygon(float offset)
528 | { return OffsetPolygon(offset, true, true); }
529 |
530 | Polygon OffsetPolygon(float offset, bool simplify, bool rounded)
531 | {
532 | // Calculate Polygon-Clipper scale.
533 | float maximum = Mathf.Max(bounds.width, bounds.height) + offset * 2.0f + offset;
534 | float maximumScale = (float)Int32.MaxValue / maximum;
535 | float scale = Mathf.Min(clipperScale, maximumScale);
536 |
537 |
538 | // Convert to Clipper.
539 | Paths paths = new Paths();
540 | {
541 | Path path = new Path();
542 | EnumeratePoints((Vector2 eachPoint) =>
543 | {
544 | path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
545 | });
546 | paths.Add(path);
547 | }
548 | foreach (Polygon eachPolygon in polygons)
549 | {
550 | Path path = new Path();
551 | eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
552 | {
553 | path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
554 | });
555 | paths.Add(path);
556 | }
557 |
558 | // Mode.
559 | JoinType joinType = (rounded) ? JoinType.jtRound : JoinType.jtMiter;
560 |
561 | // Clipper offset.
562 | Paths offsetPaths = new Paths();
563 | ClipperOffset clipperOffset = new ClipperOffset();
564 | if (rounded) { clipperOffset.ArcTolerance = 0.25 * clipperArcTolerance; } // "The default ArcTolerance is 0.25 units." from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
565 | clipperOffset.AddPaths(paths, joinType, EndType.etClosedPolygon);
566 | clipperOffset.Execute(ref offsetPaths, (double)offset * scale);
567 |
568 | // Remove self intersections (if requested).
569 | if (simplify)
570 | { offsetPaths = Clipper.SimplifyPolygons(offsetPaths); }
571 |
572 | // Convert from Clipper.
573 | Polygon offsetPolygon = null;
574 | for (int index = 0; index < offsetPaths.Count; index++)
575 | {
576 | Path eachSolutionPath = offsetPaths[index];
577 | Polygon eachSolutionPolygon = PolygonFromClipperPath(eachSolutionPath, scale);
578 |
579 | if (index == 0)
580 | {
581 | offsetPolygon = Polygon.PolygonWithPoints(eachSolutionPolygon.points); // Copy
582 | }
583 | else
584 | {
585 | offsetPolygon.AddPolygon(eachSolutionPolygon);
586 | }
587 | }
588 |
589 | // Back to Polygon.
590 | return offsetPolygon;
591 | }
592 |
593 | public Polygon UnionPolygon()
594 | {
595 | // Calculate Polygon-Clipper scale.
596 | float maximum = Mathf.Max(bounds.width, bounds.height);
597 | float maximumScale = (float)Int32.MaxValue / maximum;
598 | float scale = Mathf.Min(clipperScale, maximumScale);
599 |
600 | // Convert to Clipper.
601 | Paths subjectPaths = new Paths();
602 | Paths clipPaths = new Paths();
603 | {
604 | Path path = new Path();
605 | EnumeratePoints((Vector2 eachPoint) =>
606 | {
607 | path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
608 | });
609 | subjectPaths.Add(path);
610 | }
611 | foreach (Polygon eachPolygon in polygons)
612 | {
613 | Path path = new Path();
614 | eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
615 | {
616 | path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
617 | });
618 | clipPaths.Add(path);
619 | }
620 |
621 | // Clipper union.
622 | Paths unionPaths = new Paths();
623 | Clipper clipper = new Clipper();
624 | clipper.AddPaths(subjectPaths, PolyType.ptSubject, true);
625 | clipper.AddPaths(clipPaths, PolyType.ptClip, true);
626 | clipper.Execute(ClipType.ctUnion, unionPaths);
627 |
628 | // Remove self intersections.
629 | Paths simplifiedUnionPaths = new Paths();
630 | simplifiedUnionPaths = Clipper.SimplifyPolygons(unionPaths);
631 |
632 | // Convert from Cipper.
633 | Polygon simplifiedUnionPolygon = null;
634 | for (int index = 0; index < simplifiedUnionPaths.Count; index++)
635 | {
636 | Path eachSolutionPath = simplifiedUnionPaths[index];
637 | Polygon eachSolutionPolygon = PolygonFromClipperPath(eachSolutionPath, scale);
638 |
639 | if (index == 0)
640 | {
641 | simplifiedUnionPolygon = Polygon.PolygonWithPoints(eachSolutionPolygon.points); // Copy
642 | }
643 | else
644 | {
645 | simplifiedUnionPolygon.AddPolygon(eachSolutionPolygon);
646 | }
647 | }
648 |
649 | // Back to Polygon.
650 | return simplifiedUnionPolygon;
651 | }
652 |
653 | private Polygon PolygonFromClipperPath(Path path, float scale)
654 | {
655 | List points = new List();
656 | for (int index = path.Count - 1; index >= 0; index--) // Reverse enumeration (to flip normals)
657 | {
658 | IntPoint eachPoint = path[index];
659 | points.Add(new Vector2(eachPoint.X / scale, eachPoint.Y / scale));
660 | }
661 | return Polygon.PolygonWithPointList(points);
662 | }
663 |
664 | #endregion
665 |
666 |
667 | #region Geometry features (Transformations)
668 |
669 | public void Reverse()
670 | {
671 | // May be a feature later on (reverse `_points` using `System.Array.Copy()`.
672 | }
673 |
674 | public void AlignCentered()
675 | {
676 | Vector2 originalCenter = bounds.center;
677 | Vector2 offset = -originalCenter;
678 | Translate(offset);
679 | }
680 |
681 | public void Translate(Vector2 translation)
682 | {
683 | // Apply to each point.
684 | for (int index = 0; index < _points.Length; index++)
685 | {
686 | _points[index] += translation;
687 | }
688 |
689 | // Apply to each sub-polygon.
690 | foreach (Polygon eachPolygon in polygons)
691 | {
692 | eachPolygon.Translate(translation);
693 | }
694 |
695 | // Polygon calculations.
696 | Calculate();
697 |
698 | // Update (bounds).
699 | // _bounds.position += translation;
700 | }
701 |
702 | public void Scale(Vector2 scale)
703 | {
704 | if (scale == Vector2.one) return; // Only if any
705 |
706 | // Apply to each point.
707 | for (int index = 0; index < _points.Length; index++)
708 | {
709 | _points[index].x *= scale.x;
710 | _points[index].y *= scale.y;
711 | }
712 |
713 | // Apply to each sub-polygon.
714 | foreach (Polygon eachPolygon in polygons)
715 | {
716 | eachPolygon.Scale(scale);
717 | }
718 |
719 | // Polygon calculations.
720 | Calculate();
721 | }
722 |
723 | #endregion
724 |
725 |
726 | }
727 | }
728 |
--------------------------------------------------------------------------------