Skip to content

Commit

Permalink
Fix overlaps()
Browse files Browse the repository at this point in the history
This corrects the behaviour of overlaps() for both areas and
volumes. The function was incorrectly treating the upper bounds of
areas as inclusive as opposed to exclusive.

Fix #12
  • Loading branch information
io7m committed May 8, 2017
1 parent d29016f commit fa93b60
Show file tree
Hide file tree
Showing 12 changed files with 828 additions and 208 deletions.
6 changes: 6 additions & 0 deletions README-CHANGES.xml
Expand Up @@ -23,6 +23,12 @@
<c:ticket>9</c:ticket>
<c:summary>Add volume types.</c:summary>
</c:item>
<c:item>
<c:date>2017-05-08</c:date>
<c:type-code-fix/>
<c:ticket>12</c:ticket>
<c:summary>Fix contains() for areas and volumes.</c:summary>
</c:item>
</c:release>

<c:release c:ticket-system="com.github.io7m.jregions">
Expand Down
23 changes: 15 additions & 8 deletions com.io7m.jregions.core/src/main/string-template/Areas.st
Expand Up @@ -1267,14 +1267,21 @@ public final class <className>
<opClass>.notNullArea(a, "a");
<opClass>.notNullArea(b, "b");

if (<opClass>.compare(a.minimumX(), b.maximumX()) \>= 0 || <opClass>.compare(a.maximumX(), b.minimumX()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumY(), b.maximumY()) \>= 0 || <opClass>.compare(a.maximumY(), b.minimumY()) \< 0) {
return false;
}

return true;
final <scalarType> a_x0 = a.minimumX();
final <scalarType> a_x1 = a.maximumX();
final <scalarType> a_y0 = a.minimumY();
final <scalarType> a_y1 = a.maximumY();
final <scalarType> b_x0 = b.minimumX();
final <scalarType> b_x1 = b.maximumX();
final <scalarType> b_y0 = b.minimumY();
final <scalarType> b_y1 = b.maximumY();

final boolean c0 = <opClass>.compare(a_x0, b_x1) \< 0;
final boolean c1 = <opClass>.compare(a_x1, b_x0) \> 0;
final boolean c2 = <opClass>.compare(a_y0, b_y1) \< 0;
final boolean c3 = <opClass>.compare(a_y1, b_y0) \> 0;

return c0 && c1 && c2 && c3;
}

/**
Expand Down
23 changes: 15 additions & 8 deletions com.io7m.jregions.core/src/main/string-template/PAreas.st
Expand Up @@ -1291,14 +1291,21 @@ public final class <className>
<opClass>.notNullArea(a, "a");
<opClass>.notNullArea(b, "b");

if (<opClass>.compare(a.minimumX(), b.maximumX()) \>= 0 || <opClass>.compare(a.maximumX(), b.minimumX()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumY(), b.maximumY()) \>= 0 || <opClass>.compare(a.maximumY(), b.minimumY()) \< 0) {
return false;
}

return true;
final <scalarType> a_x0 = a.minimumX();
final <scalarType> a_x1 = a.maximumX();
final <scalarType> a_y0 = a.minimumY();
final <scalarType> a_y1 = a.maximumY();
final <scalarType> b_x0 = b.minimumX();
final <scalarType> b_x1 = b.maximumX();
final <scalarType> b_y0 = b.minimumY();
final <scalarType> b_y1 = b.maximumY();

final boolean c0 = <opClass>.compare(a_x0, b_x1) \< 0;
final boolean c1 = <opClass>.compare(a_x1, b_x0) \> 0;
final boolean c2 = <opClass>.compare(a_y0, b_y1) \< 0;
final boolean c3 = <opClass>.compare(a_y1, b_y0) \> 0;

return c0 && c1 && c2 && c3;
}

/**
Expand Down
32 changes: 21 additions & 11 deletions com.io7m.jregions.core/src/main/string-template/PVolumes.st
Expand Up @@ -249,17 +249,27 @@ public final class <className>
<opClass>.notNullVolume(a, "a");
<opClass>.notNullVolume(b, "b");

if (<opClass>.compare(a.minimumX(), b.maximumX()) \>= 0 || <opClass>.compare(a.maximumX(), b.minimumX()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumY(), b.maximumY()) \>= 0 || <opClass>.compare(a.maximumY(), b.minimumY()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumZ(), b.maximumZ()) \>= 0 || <opClass>.compare(a.maximumZ(), b.minimumZ()) \< 0) {
return false;
}

return true;
final <scalarType> a_x0 = a.minimumX();
final <scalarType> a_x1 = a.maximumX();
final <scalarType> a_y0 = a.minimumY();
final <scalarType> a_y1 = a.maximumY();
final <scalarType> a_z0 = a.minimumZ();
final <scalarType> a_z1 = a.maximumZ();
final <scalarType> b_x0 = b.minimumX();
final <scalarType> b_x1 = b.maximumX();
final <scalarType> b_y0 = b.minimumY();
final <scalarType> b_y1 = b.maximumY();
final <scalarType> b_z0 = b.minimumZ();
final <scalarType> b_z1 = b.maximumZ();

final boolean c0 = <opClass>.compare(a_x0, b_x1) \< 0;
final boolean c1 = <opClass>.compare(a_x1, b_x0) \> 0;
final boolean c2 = <opClass>.compare(a_y0, b_y1) \< 0;
final boolean c3 = <opClass>.compare(a_y1, b_y0) \> 0;
final boolean c4 = <opClass>.compare(a_z0, b_z1) \< 0;
final boolean c5 = <opClass>.compare(a_z1, b_z0) \> 0;

return c0 && c1 && c2 && c3 && c4 && c5;
}

/**
Expand Down
32 changes: 21 additions & 11 deletions com.io7m.jregions.core/src/main/string-template/Volumes.st
Expand Up @@ -223,17 +223,27 @@ public final class <className>
<opClass>.notNullVolume(a, "a");
<opClass>.notNullVolume(b, "b");

if (<opClass>.compare(a.minimumX(), b.maximumX()) \>= 0 || <opClass>.compare(a.maximumX(), b.minimumX()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumY(), b.maximumY()) \>= 0 || <opClass>.compare(a.maximumY(), b.minimumY()) \< 0) {
return false;
}
if (<opClass>.compare(a.minimumZ(), b.maximumZ()) \>= 0 || <opClass>.compare(a.maximumZ(), b.minimumZ()) \< 0) {
return false;
}

return true;
final <scalarType> a_x0 = a.minimumX();
final <scalarType> a_x1 = a.maximumX();
final <scalarType> a_y0 = a.minimumY();
final <scalarType> a_y1 = a.maximumY();
final <scalarType> a_z0 = a.minimumZ();
final <scalarType> a_z1 = a.maximumZ();
final <scalarType> b_x0 = b.minimumX();
final <scalarType> b_x1 = b.maximumX();
final <scalarType> b_y0 = b.minimumY();
final <scalarType> b_y1 = b.maximumY();
final <scalarType> b_z0 = b.minimumZ();
final <scalarType> b_z1 = b.maximumZ();

final boolean c0 = <opClass>.compare(a_x0, b_x1) \< 0;
final boolean c1 = <opClass>.compare(a_x1, b_x0) \> 0;
final boolean c2 = <opClass>.compare(a_y0, b_y1) \< 0;
final boolean c3 = <opClass>.compare(a_y1, b_y0) \> 0;
final boolean c4 = <opClass>.compare(a_z0, b_z1) \< 0;
final boolean c5 = <opClass>.compare(a_z1, b_z0) \> 0;

return c0 && c1 && c2 && c3 && c4 && c5;
}

/**
Expand Down
@@ -0,0 +1,214 @@
/*
* Copyright © 2017 <code@io7m.com> http://io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package com.io7m.jregions.tests.bugs;

import com.io7m.jregions.core.parameterized.areas.PAreaBD;
import com.io7m.jregions.core.parameterized.areas.PAreaBI;
import com.io7m.jregions.core.parameterized.areas.PAreaD;
import com.io7m.jregions.core.parameterized.areas.PAreaF;
import com.io7m.jregions.core.parameterized.areas.PAreaI;
import com.io7m.jregions.core.parameterized.areas.PAreaL;
import com.io7m.jregions.core.parameterized.areas.PAreasBD;
import com.io7m.jregions.core.parameterized.areas.PAreasBI;
import com.io7m.jregions.core.parameterized.areas.PAreasD;
import com.io7m.jregions.core.parameterized.areas.PAreasF;
import com.io7m.jregions.core.parameterized.areas.PAreasI;
import com.io7m.jregions.core.parameterized.areas.PAreasL;
import com.io7m.jregions.core.unparameterized.areas.AreaBD;
import com.io7m.jregions.core.unparameterized.areas.AreaBI;
import com.io7m.jregions.core.unparameterized.areas.AreaD;
import com.io7m.jregions.core.unparameterized.areas.AreaF;
import com.io7m.jregions.core.unparameterized.areas.AreaI;
import com.io7m.jregions.core.unparameterized.areas.AreaL;
import com.io7m.jregions.core.unparameterized.areas.AreasBD;
import com.io7m.jregions.core.unparameterized.areas.AreasBI;
import com.io7m.jregions.core.unparameterized.areas.AreasD;
import com.io7m.jregions.core.unparameterized.areas.AreasF;
import com.io7m.jregions.core.unparameterized.areas.AreasI;
import com.io7m.jregions.core.unparameterized.areas.AreasL;
import org.junit.Assert;
import org.junit.Test;

import java.math.BigDecimal;
import java.math.BigInteger;

public final class Bug12AreaTest
{
@Test
public void testBug12L()
{
final AreaL area0 =
AreaL.of(0L, 10L, 0L, 10L);
final AreaL area1 =
AreaL.of(10L, 20L, 10L, 20L);

Assert.assertFalse(AreasL.overlaps(area0, area1));
}

@Test
public void testBug12I()
{
final AreaI area0 =
AreaI.of(0, 10, 0, 10);
final AreaI area1 =
AreaI.of(10, 20, 10, 20);

Assert.assertFalse(AreasI.overlaps(area0, area1));
}

@Test
public void testBug12D()
{
final AreaD area0 =
AreaD.of(0.0, 10.0, 0.0, 10.0);
final AreaD area1 =
AreaD.of(10.0, 20.0, 10.0, 20.0);

Assert.assertFalse(AreasD.overlaps(area0, area1));
}

@Test
public void testBug12F()
{
final AreaF area0 =
AreaF.of(0.0F, 10.0F, 0.0F, 10.0F);
final AreaF area1 =
AreaF.of(10.0F, 20.0F, 10.0F, 20.0F);

Assert.assertFalse(AreasF.overlaps(area0, area1));
}

@Test
public void testBug12BI()
{
final AreaBI area0 =
AreaBI.of(
BigInteger.valueOf(0L),
BigInteger.valueOf(10L),
BigInteger.valueOf(0L),
BigInteger.valueOf(10L));
final AreaBI area1 =
AreaBI.of(
BigInteger.valueOf(10L),
BigInteger.valueOf(20L),
BigInteger.valueOf(10L),
BigInteger.valueOf(20L));

Assert.assertFalse(AreasBI.overlaps(area0, area1));
}

@Test
public void testBug12BD()
{
final AreaBD area0 =
AreaBD.of(
BigDecimal.valueOf(0L),
BigDecimal.valueOf(10L),
BigDecimal.valueOf(0L),
BigDecimal.valueOf(10L));
final AreaBD area1 =
AreaBD.of(
BigDecimal.valueOf(10L),
BigDecimal.valueOf(20L),
BigDecimal.valueOf(10L),
BigDecimal.valueOf(20L));

Assert.assertFalse(AreasBD.overlaps(area0, area1));
}

@Test
public void testBugP12L()
{
final PAreaL<Object> area0 =
PAreaL.of(0L, 10L, 0L, 10L);
final PAreaL<Object> area1 =
PAreaL.of(10L, 20L, 10L, 20L);

Assert.assertFalse(PAreasL.overlaps(area0, area1));
}

@Test
public void testBugP12I()
{
final PAreaI<Object> area0 =
PAreaI.of(0, 10, 0, 10);
final PAreaI<Object> area1 =
PAreaI.of(10, 20, 10, 20);

Assert.assertFalse(PAreasI.overlaps(area0, area1));
}

@Test
public void testBugP12D()
{
final PAreaD<Object> area0 =
PAreaD.of(0.0, 10.0, 0.0, 10.0);
final PAreaD<Object> area1 =
PAreaD.of(10.0, 20.0, 10.0, 20.0);

Assert.assertFalse(PAreasD.overlaps(area0, area1));
}

@Test
public void testBugP12F()
{
final PAreaF<Object> area0 =
PAreaF.of(0.0F, 10.0F, 0.0F, 10.0F);
final PAreaF<Object> area1 =
PAreaF.of(10.0F, 20.0F, 10.0F, 20.0F);

Assert.assertFalse(PAreasF.overlaps(area0, area1));
}

@Test
public void testBugP12BI()
{
final PAreaBI<Object> area0 =
PAreaBI.of(
BigInteger.valueOf(0L),
BigInteger.valueOf(10L),
BigInteger.valueOf(0L),
BigInteger.valueOf(10L));
final PAreaBI<Object> area1 =
PAreaBI.of(
BigInteger.valueOf(10L),
BigInteger.valueOf(20L),
BigInteger.valueOf(10L),
BigInteger.valueOf(20L));

Assert.assertFalse(PAreasBI.overlaps(area0, area1));
}

@Test
public void testBugP12BD()
{
final PAreaBD<Object> area0 =
PAreaBD.of(
BigDecimal.valueOf(0L),
BigDecimal.valueOf(10L),
BigDecimal.valueOf(0L),
BigDecimal.valueOf(10L));
final PAreaBD<Object> area1 =
PAreaBD.of(
BigDecimal.valueOf(10L),
BigDecimal.valueOf(20L),
BigDecimal.valueOf(10L),
BigDecimal.valueOf(20L));

Assert.assertFalse(PAreasBD.overlaps(area0, area1));
}
}

0 comments on commit fa93b60

Please sign in to comment.