package graphmatcher.matcher.shapecontext;
import graphmatcher.graph.Graph;
import graphmatcher.graph.Vertex;
import graphmatcher.helper.AngleHelper;
import graphmatcher.helper.DistanceHelper;
import graphmatcher.matcher.MatchingOptions;
import java.awt.Point;
import java.util.Vector;
import org.apache.log4j.Logger;
public class ShapeContext {
private static Logger logger = Logger.getLogger(ShapeContext.class);
private int _numberOfNeighbours;
private int _numberOfRadiusBins;
private int _numberOfAngleBins;
private int _vertexId;
private Graph _graph;
private Point _center;
private double _maxDistance;
private double _relativDist;
private Vector<Integer>[][] _unconnectedVerticesBins, _connectedVerticesBins, _visibleVerticesBins;
private MatchingOptions matchingOptions;
public ShapeContext(int vertexId, Graph graph, int numberOfNeighbours, MatchingOptions matchingOptions) {
_numberOfNeighbours = numberOfNeighbours;
this.matchingOptions = matchingOptions;
_numberOfAngleBins = matchingOptions.numberOfAngleBins;
_numberOfRadiusBins = matchingOptions.numberOfRadiusBins;
_vertexId = vertexId;
Vertex vertex = graph.vertices()[vertexId];
_graph = graph;
_center = graph.getCenter();
_maxDistance = graph.getMaximumVertexDistanceToCenter() * 2;
double distToCenter = DistanceHelper.getDistance(_center, vertex.toPoint());
_relativDist = distToCenter / _maxDistance;
_unconnectedVerticesBins = new Vector[_numberOfAngleBins][_numberOfRadiusBins];
_connectedVerticesBins = new Vector[_numberOfAngleBins][_numberOfRadiusBins];
_visibleVerticesBins = new Vector[_numberOfAngleBins][_numberOfRadiusBins];
for (int i = 0; i < _numberOfAngleBins; i++) {
for (int j = 0; j < _numberOfRadiusBins; j++) {
_unconnectedVerticesBins[i][j] = new Vector<Integer>();
_connectedVerticesBins[i][j] = new Vector<Integer>();
_visibleVerticesBins[i][j] = new Vector<Integer>();
}
}
distributeNeighboursInBins();
}
private void distributeNeighboursInBins() {
// logger.info("Ermittele ShapeContext von Knoten " + _vertexId);
Vertex vertex = _graph.vertices()[_vertexId];
Point vertexPoint = new Point(vertex.x, vertex.y);
int[] neighbourIds = NeighbourHelper.getNeighbours(_vertexId, _graph);
for (int i = 0; i < _numberOfNeighbours; i++) {
// for (int i = neighbourIds.length-1; i > neighbourIds.length -
// Options.numberOfNeighbours; i--) {
int neighbourId = neighbourIds[i];
Vertex neighbour = _graph.vertices()[neighbourId];
Point neighbourPoint = new Point(neighbour.x, neighbour.y);
if (matchingOptions.isNoRotation()) {
_center = new Point(vertexPoint.x + 1, vertexPoint.y);
}
double angle = AngleHelper.getAngle(vertexPoint, _center, neighbourPoint);
while (angle >= 360) {
angle -= 360;
}
int angleBin = (int) Math.floor((_numberOfAngleBins * (angle / 360)));
double distance = DistanceHelper.getDistance(vertexPoint, neighbourPoint);
int radiusBin = (int) Math.floor((distance / _maxDistance) * _numberOfRadiusBins);
boolean connected = _graph.isConnected(_vertexId, neighbourId);
double shortestPath = _graph.getShorstestPath(_vertexId, neighbourId);
// double directPath = _graph.getDistance(_vertexId, neighbourId);
boolean indirectConnected = (shortestPath <= distance * 1.5);
if (connected && !indirectConnected) {
// System.out.println("sp:" + shortestPath);
// System.out.println("dist:" + distance);
throw new RuntimeException("Knoten durch Kante verbunden, aber nicht indirekt (ShapeContext)");
}
if (connected || indirectConnected) {
// if (connected) {
// Eimer f�r verbundene Knoten
if (radiusBin > _numberOfRadiusBins - 1) {
_connectedVerticesBins[angleBin][_numberOfRadiusBins - 1].add(neighbourId);
} else {
_connectedVerticesBins[angleBin][radiusBin].add(neighbourId);
}
} else {
// Eimer f�r nicht verbundene Knoten
if (radiusBin > _numberOfRadiusBins - 1) {
_unconnectedVerticesBins[angleBin][_numberOfRadiusBins - 1].add(neighbourId);
} else {
_unconnectedVerticesBins[angleBin][radiusBin].add(neighbourId);
}
}
if (_graph.isVisible(_vertexId, neighbourId)) {
if (radiusBin > _numberOfRadiusBins - 1) {
_visibleVerticesBins[angleBin][_numberOfRadiusBins - 1].add(neighbourId);
} else {
_visibleVerticesBins[angleBin][radiusBin].add(neighbourId);
}
}
}
}
public Vector<Integer>[][] getUnconnectedVerticesBins() {
return _unconnectedVerticesBins;
}
public Vector<Integer>[][] getConnectedVerticesBins() {
return _connectedVerticesBins;
}
public Vector<Integer>[][] getVisibleVerticesBins() {
return _visibleVerticesBins;
}
public double getRelativeDistance() {
return _relativDist;
}
public int getVertexID() {
return _vertexId;
}
public Graph getGraph() {
return _graph;
}
public int getNumberOfNeighbours() {
return _numberOfNeighbours;
}
}