-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add intersects function
#6967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add intersects function
#6967
Changes from 1 commit
1c5868b
fd4a6a1
ab235b8
4fb7739
3419811
9641e08
b2f3cc7
a11a20d
7508fe8
17e52e8
83a60e2
281fd94
d21470c
7256252
77bec29
2a3cd02
da8e9a7
d853d05
292b7be
e074729
7055bdc
527ae8e
e7a8662
0800a0e
602fee7
ad81da9
69d4c8a
8860a4a
e7b2a71
30dbba2
8822207
8e0e0c7
970b508
1d1a320
bba4264
2fb19f8
9f596bc
29936a8
08c5997
c6aa7c0
6a0e2e0
ac13533
d88de71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.odk.collect.shared | ||
|
|
||
| /** | ||
| * Simple helper to allow writing neater [QuickCheck](https://en.wikipedia.org/wiki/QuickCheck) | ||
| * style tests. | ||
| */ | ||
| fun <Input, Output> ((Input) -> Output).quickCheck( | ||
| iterations: Int, | ||
| generator: Sequence<Input>, | ||
| checks: (Input, Output) -> Unit | ||
| ) { | ||
| generator.take(iterations).forEach { input -> | ||
| val output = this(input) | ||
| checks(input, output) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ package org.odk.collect.shared.geometry | |
| import org.hamcrest.MatcherAssert.assertThat | ||
| import org.hamcrest.Matchers.equalTo | ||
| import org.junit.Test | ||
| import org.odk.collect.shared.quickCheck | ||
| import kotlin.random.Random | ||
|
|
||
| class GeometryTest { | ||
|
|
@@ -208,10 +209,10 @@ class GeometryTest { | |
|
|
||
| @Test | ||
| fun `Trace#intersects satisfies metamorphic relationships`() { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @grzesiek2010 Here's the metamorphic test I've added. It currently checks that intersection is consistent when reversing/scaling traces and that adding an intersecting segment to a non-intersecting trace causes
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll also see that I had to add an epsilon to the collinearity check to handle precision errors and that actually got revealed because of this test which was pretty cool. I'm going to involve @getodk/testers now so we can get some more feedback on using this. It'll be interesting to see if our current calculations are actually too precise when playing around in the real world. |
||
| repeat(1000) { | ||
| val trace = generateTrace() | ||
| val intersects = trace.intersects() | ||
|
|
||
| { trace: Trace -> trace.intersects() }.quickCheck( | ||
| iterations = 1000, | ||
| generator = getTraceGenerator() | ||
| ) { trace, intersects -> | ||
| // Check intersects is consistent when trace is reversed | ||
| val reversedTrace = Trace(trace.points.reversed()) | ||
| assertThat( | ||
|
|
@@ -299,23 +300,25 @@ class GeometryTest { | |
| assertThat(interpolatedPoint.within(segment), equalTo(true)) | ||
| } | ||
|
|
||
| private fun generateTrace(maxLength: Int = 10, maxCoordinate: Double = 100.0): Trace { | ||
| val length = Random.nextInt(2, maxLength) | ||
| val trace = Trace(0.until(length).map { | ||
| Point( | ||
| Random.nextDouble(maxCoordinate * -1, maxCoordinate), | ||
| Random.nextDouble(maxCoordinate * -1, maxCoordinate) | ||
| ) | ||
| }) | ||
|
|
||
| return if (trace.isClosed()) { | ||
| trace | ||
| } else { | ||
| val shouldClose = Random.nextBoolean() | ||
| if (shouldClose) { | ||
| trace.copy(points = trace.points + trace.points.first()) | ||
| } else { | ||
| private fun getTraceGenerator(maxLength: Int = 10, maxCoordinate: Double = 100.0): Sequence<Trace> { | ||
| return generateSequence { | ||
| val length = Random.nextInt(2, maxLength) | ||
| val trace = Trace(0.until(length).map { | ||
| Point( | ||
| Random.nextDouble(maxCoordinate * -1, maxCoordinate), | ||
| Random.nextDouble(maxCoordinate * -1, maxCoordinate) | ||
| ) | ||
| }) | ||
|
|
||
| if (trace.isClosed()) { | ||
| trace | ||
| } else { | ||
| val shouldClose = Random.nextBoolean() | ||
| if (shouldClose) { | ||
| trace.copy(points = trace.points + trace.points.first()) | ||
| } else { | ||
| trace | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did have a quick look at using an existing framework (https://github.com/pholser/junit-quickcheck for example), but it felt like we didn't really need anything so heavy yet. Maybe if we end up writing more of these kinds of tests down the line!