Skip to content
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

Hexagons #13

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
70 changes: 65 additions & 5 deletions src/main/java/com/opennars/applications/crossing/Crossing.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
import processing.event.MouseEvent;

public class Crossing extends PApplet {
public static double hexagonWidth = 10.0;
public static double hexagonHeight = 10.0;

static HexagonMapping hexagonMapping = new HexagonMapping(hexagonWidth, hexagonHeight);

Nar nar;
int entityID = 1;

Expand All @@ -49,6 +54,7 @@ public void setup() {
nar.narParameters.VOLUME = 0;
nar.narParameters.DURATION*=10;
NarListener listener = new NarListener(cameras.get(0), nar, predictions, disappointments, entities);
listener.crossing = this;
nar.on(Events.TaskAdd.class, listener);
nar.on(DISAPPOINT.class, listener);
} catch (Exception ex) {
Expand Down Expand Up @@ -78,7 +84,31 @@ public void setup() {
String narsese = "<(*,{" + l.id + "}," + pos + ") --> at>.";
nar.addInput(narsese);
}*/



/**
* test if the hexagon mapping works as expected
*/
/*
for(int y=500;y<500+60; y+=1) {
for(int x=500;x<500+60; x+= 1) {

Vec2Int mapped = hexagonMapping.map(x, y);

int color = mapped.hashCode() % 4;

DebugObject d = new DebugObject(x, y);
d.colorR = (float)color / 4.0f;

debugObjects.add(d);
}
}
*/





size(1000, 1000);
frameRate(fps);
new NarSimpleGUI(nar);
Expand All @@ -88,6 +118,9 @@ public void setup() {
List<TrafficLight> trafficLights = new ArrayList<TrafficLight>();
List<Entity> entities = new ArrayList<Entity>();
List<Camera> cameras = new ArrayList<Camera>();

List<DebugObject> debugObjects = new ArrayList<>();

int t = 0;
public static boolean showAnomalies = false;

Expand All @@ -111,19 +144,28 @@ public void draw() {
nar.addInput(questions);
}
}
for (int i = 0; i < 1000; i += Util.discretization) {
stroke(128);
line(0, i, 1000, i);
line(i, 0, i, 1000);

for (int y=50;y<80;y++) {
for (int x=40;x<65;x++) {
final double[] pos = hexagonMapping.calcPositionOfHexagon(x, y);
drawHexagon(pos[0], pos[1]);
}
}


for (Entity e : entities) {
e.draw(this, streets, trafficLights, entities, null, 0);
}
for (TrafficLight tl : trafficLights) {
tl.draw(this, t);
}

for (final DebugObject iDebug : debugObjects) {
this.stroke(0, 0); // no stroke
this.fill(iDebug.colorR * 255.0f, 0, 0);
this.rect((float)(iDebug.posX-0.5), (float)(iDebug.posY-0.5), 1, 1);
}

// tick
for (Entity ie : entities) {
ie.tick();
Expand Down Expand Up @@ -157,6 +199,21 @@ public void draw() {
System.out.println("Concepts: " + nar.memory.concepts.size());
}

private void drawHexagon(final double x, final double y) {
stroke(0);
// used for debugging the "real position"
rect((float)x-1.5f, (float)y-1.5f, 3, 3);

stroke(128);

for (int i=0; i < hexagonMapping.verticesRelative.length; i++) {
final double[] aRel = hexagonMapping.verticesRelative[i];
final double[] bRel = hexagonMapping.verticesRelative[(i+1) % hexagonMapping.verticesRelative.length];

line((float)(x + aRel[0]), (float)(y + aRel[1]), (float)(x + bRel[0]), (float)(y + bRel[1]));
}
}

public void removeOutdatedPredictions(List<Prediction> predictions) {
List<Prediction> toDelete = new ArrayList<Prediction>();
for(Prediction pred : predictions) {
Expand Down Expand Up @@ -213,4 +270,7 @@ public static void main(String[] args) {
new IncidentSimulator().show();
PApplet.runSketch(args2, mp);
}



}
14 changes: 14 additions & 0 deletions src/main/java/com/opennars/applications/crossing/DebugObject.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.opennars.applications.crossing;

public class DebugObject {
public double posX;
public double posY;
public int remainingTime = 100;

public float colorR = 1.0f;

public DebugObject(final double posX, final double posY) {
this.posX = posX;
this.posY = posY;
}
}
12 changes: 10 additions & 2 deletions src/main/java/com/opennars/applications/crossing/Entity.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,21 @@ public void draw(PApplet applet, List<Street> streets, List<TrafficLight> traffi
//float posYDiscrete = (((int) this.posY)/Util.discretization * Util.discretization);
applet.translate((float) posX, (float) posY);
applet.rotate((float) angle);

if(truth == null) {
applet.rect(0, 0, Util.discretization*scale, Util.discretization/2*scale);
final float width = Util.discretization/2*scale;
applet.rect(0.0f*Util.discretization*scale, -0.5f*width, Util.discretization*scale, width);
}
applet.ellipse(2.5f, 2.5f, Util.discretization*scale, Util.discretization*scale);
applet.ellipse(0, 0, Util.discretization*scale, Util.discretization*scale);

applet.popMatrix();
applet.fill(0);
applet.text(String.valueOf(id), (float)posX, (float)posY);

// used for debugging the "real position"
applet.rect((float)posX-1.5f, (float)posY-1.5f, 3, 3);


if(truth != null) {
return;
}
Expand Down
216 changes: 216 additions & 0 deletions src/main/java/com/opennars/applications/crossing/HexagonMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* The MIT License
*
* Copyright 2018 The OpenNARS authors.
*
* 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:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 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.
*/
package com.opennars.applications.crossing;

public class HexagonMapping {
//private final double[][] positions;
//private final double[] distances;
public final double[][] verticesRelative;

public double width; // width of hexagon
public double height; // height of hexagon

public HexagonMapping(final double width, final double height) {
this.width = width;
this.height = height;

// relative positions of the vertices of a single hexagon
verticesRelative = new double[][]{
{width * -0.5, height * -0.25},
{width * -0.5, height * 0.25},

{0.0, height * 0.5},

{width * 0.5, height * 0.25},
{width * 0.5, height * -0.25},

{0.0, height * -0.5},
};

/*
positions = new double[][]{
{0.5 * width, -0.25 * height},
{1.5 * width, -0.25 * height},

{0.0, 0.5 * height},
{width, 0.5 * height},
{width + width, 0.5 * height},

{0.5 * width, 1.25 * height},
{1.5 * width, 1.25 * height},
};

distances = new double[positions.length];
*/
}

public double[] calcPositionOfHexagon(final int x, final int y) {
final double offsetX = (y % 2) == 0 ? 0.0 : -0.5*width;

double resultX = (x + 1) * width + offsetX;
double resultY = 0.5*height + 0.75*height*y;
return new double[]{resultX, resultY};
}

public Vec2Int map(final double x, final double y) {
for(int ix=0;ix<100;ix++) {
for(int iy=0;iy<100;iy++) {
final double[] positionOfHexagon = calcPositionOfHexagon(ix, iy);



boolean isInHexagon = isInHexagonRelative(x - positionOfHexagon[0], y - positionOfHexagon[1]);

// HACK
/*
isInHexagon = isInPolygon(x - positionOfHexagon[0], y - positionOfHexagon[1],
0, 0,
5, 0,
0, 5
);
*/

if (isInHexagon) {
return new Vec2Int(ix, iy);
}
}
}

// default!
return new Vec2Int(5, 0);

/*
final int ix = (int)(x / (width*2.0));
final int iy = (int)(y / (height*1.5));

final double relX = x - ix * (width*2.0);
final double relY = y - iy * (height*1.5);

final Vec2Int relativeHexagonIndices = mapGroupToRelCell(relX, relY);
return new Vec2Int(relativeHexagonIndices.x + ix*2, relativeHexagonIndices.y + iy*2);
*/
}

// public for testing
public boolean isInHexagonRelative(final double x, final double y) {
if (x==0 && y==0) {
return true;
}

for(int i=0;i<6;i++) {
final int iNext = (i + 1) % 6;
final int iOtherSide = (i + 4) % 6;

final boolean isInPolygonOfHexagon = isInPolygon(
x, y,
verticesRelative[iNext][0], verticesRelative[iNext][1],
verticesRelative[i][0], verticesRelative[i][1],
verticesRelative[iOtherSide][0], verticesRelative[iOtherSide][1]
);
if (isInPolygonOfHexagon) {
return true;
}
}

return false;
}


public static boolean isInPolygon(final double x, final double y, final double x0, final double y0, final double x1, final double y1, final double x2, final double y2) {
final boolean side0 = side(x, y, x0, y0, x1, y1);
final boolean side1 = side(x, y, x1, y1, x2, y2);
final boolean side2 = side(x, y, x2, y2, x0, y0);

return side0 && side1 && side2;
}

public static boolean side(final double x, final double y, final double ax, final double ay, final double bx, final double by) {
final double dx = bx - ax;
final double dy = by - ay;

// perpendicular direction - which is the orientation of the edge
final double idx = -dy;
final double idy = dx;

final double pdx = x - ax;
final double pdy = y - ay;

// side is computed by direction and difference
return dot(idx, idy, pdx, pdy) >= 0.0;
}

private static double dot(final double ax, final double ay, final double bx, final double by) {
return ax*bx + ay*by;
}



/*
private Vec2Int mapGroupToRelCell(final double x, final double y) {
// see https://www.redblobgames.com/grids/hexagons/ for illustration



for(int i=0;i<positions.length;i++) {
distances[i] = Util.distance(x, y, positions[i][0], positions[i][0]);
}

int minDistanceIdx = 0;
double minDistance = distances[0];
for(int i=0;i<distances.length;i++) {
if (distances[i] < minDistance) {
minDistanceIdx = i;
minDistance = distances[i];
}
}


// fetch coordinate by index
if (minDistanceIdx == 0) {
return new Vec2Int(0, -1);
}
else if (minDistanceIdx == 1) {
return new Vec2Int(1, -1);
}

else if (minDistanceIdx == 2) {
return new Vec2Int(-1, 0);
}
else if (minDistanceIdx == 3) {
return new Vec2Int(0, 0);
}
else if (minDistanceIdx == 4) {
return new Vec2Int(1, 0);
}

else if (minDistanceIdx == 5) {
return new Vec2Int(0, 1);
}
else {
return new Vec2Int(1, 1);
}
}

*/
}
Loading