blob: 043d933e1f3fd75e7dad4869b7840b9a1437e279 [file] [log] [blame]
package org.eclipse.stem.graphgenerators.impl;
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Armin Weiser, Matthias Filter
* Bundesinstitut für Risikobewertung
* FG 43 - Epidemiologie und Zoonosen
* Diedersdorfer Weg 1, 12277 Berlin
*
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.awt.Color;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.stem.core.common.CommonFactory;
import org.eclipse.stem.core.common.CommonPackage;
import org.eclipse.stem.core.STEMURI;
import org.eclipse.stem.core.Utility;
import org.eclipse.stem.core.common.DublinCore;
import org.eclipse.stem.core.common.Identifiable;
import org.eclipse.stem.core.graph.Edge;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.graph.GraphFactory;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.graph.impl.EdgeImpl;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.definitions.Activator;
import org.eclipse.stem.definitions.adapters.spatial.geo.InlineLatLongDataProvider;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.SegmentBuilder;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLongProvider;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLongProviderAdapterFactory;
import org.eclipse.stem.definitions.edges.EdgesFactory;
import org.eclipse.stem.definitions.edges.MigrationEdge;
import org.eclipse.stem.definitions.edges.MigrationEdgeLabel;
import org.eclipse.stem.definitions.edges.MigrationEdgeLabelValue;
import org.eclipse.stem.definitions.edges.impl.EdgesFactoryImpl;
import org.eclipse.stem.definitions.labels.AreaLabel;
import org.eclipse.stem.definitions.labels.CommonBorderRelationshipLabel;
import org.eclipse.stem.definitions.labels.LabelsFactory;
import org.eclipse.stem.definitions.labels.PopulationLabel;
import org.eclipse.stem.definitions.labels.PopulationLabelValue;
import org.eclipse.stem.definitions.labels.RelativePhysicalRelationship;
import org.eclipse.stem.definitions.labels.RelativePhysicalRelationshipLabel;
import org.eclipse.stem.definitions.labels.RelativePhysicalRelationshipLabelValue;
import org.eclipse.stem.definitions.labels.impl.CommonBorderRelationshipLabelImpl;
import org.eclipse.stem.definitions.labels.impl.PopulationLabelImpl;
import org.eclipse.stem.definitions.nodes.NodesFactory;
import org.eclipse.stem.definitions.nodes.Region;
import org.eclipse.stem.graphgenerators.GraphgeneratorsPackage;
import org.eclipse.stem.graphgenerators.PajekNetGraphGenerator;
import org.eclipse.swt.graphics.Point;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Pajek Net Graph Generator</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#getDataFile_net <em>Data File net</em>}</li>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#getArea <em>Area</em>}</li>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#getContainer <em>Container</em>}</li>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#getScalingFactor <em>Scaling Factor</em>}</li>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#isFit <em>Fit</em>}</li>
* <li>{@link org.eclipse.stem.graphgenerators.impl.PajekNetGraphGeneratorImpl#isEnforceContainment <em>Enforce Containment</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class PajekNetGraphGeneratorImpl extends GraphGeneratorImpl implements PajekNetGraphGenerator {
/**
* The default value of the '{@link #getDataFile_net() <em>Data File net</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getDataFile_net()
* @generated
* @ordered
*/
protected static final String DATA_FILE_NET_EDEFAULT = "";
/**
* The cached value of the '{@link #getDataFile_net() <em>Data File net</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getDataFile_net()
* @generated
* @ordered
*/
protected String dataFile_net = DATA_FILE_NET_EDEFAULT;
/**
* The default value of the '{@link #getArea() <em>Area</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getArea()
* @generated
* @ordered
*/
protected static final double AREA_EDEFAULT = 100.0;
/**
* The cached value of the '{@link #getArea() <em>Area</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getArea()
* @generated
* @ordered
*/
protected double area = AREA_EDEFAULT;
/**
* The default value of the '{@link #getContainer() <em>Container</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getContainer()
* @generated
* @ordered
*/
protected static final URI CONTAINER_EDEFAULT = (URI)CommonFactory.eINSTANCE.createFromString(CommonPackage.eINSTANCE.getURI(), "");
/**
* The cached value of the '{@link #getContainer() <em>Container</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getContainer()
* @generated
* @ordered
*/
protected URI container = CONTAINER_EDEFAULT;
/**
* The default value of the '{@link #getScalingFactor() <em>Scaling Factor</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getScalingFactor()
* @generated
* @ordered
*/
protected static final double SCALING_FACTOR_EDEFAULT = 100.0;
/**
* The cached value of the '{@link #getScalingFactor() <em>Scaling Factor</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getScalingFactor()
* @generated
* @ordered
*/
protected double scalingFactor = SCALING_FACTOR_EDEFAULT;
private IProject project;
static double RESCALE = 100000.0;
/**
* The default value of the '{@link #isFit() <em>Fit</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isFit()
* @generated
* @ordered
*/
protected static final boolean FIT_EDEFAULT = false;
/**
* The cached value of the '{@link #isFit() <em>Fit</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isFit()
* @generated
* @ordered
*/
protected boolean fit = FIT_EDEFAULT;
/**
* The default value of the '{@link #isEnforceContainment() <em>Enforce Containment</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isEnforceContainment()
* @generated
* @ordered
*/
protected static final boolean ENFORCE_CONTAINMENT_EDEFAULT = false;
/**
* The cached value of the '{@link #isEnforceContainment() <em>Enforce Containment</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isEnforceContainment()
* @generated
* @ordered
*/
protected boolean enforceContainment = ENFORCE_CONTAINMENT_EDEFAULT;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public PajekNetGraphGeneratorImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return GraphgeneratorsPackage.Literals.PAJEK_NET_GRAPH_GENERATOR;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getDataFile_net() {
return dataFile_net;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setDataFile_net(String newDataFile_net) {
String oldDataFile_net = dataFile_net;
dataFile_net = newDataFile_net;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__DATA_FILE_NET, oldDataFile_net, dataFile_net));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public double getArea() {
return area;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setArea(double newArea) {
double oldArea = area;
area = newArea;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__AREA, oldArea, area));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public URI getContainer() {
return container;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setContainer(URI newContainer) {
URI oldContainer = container;
container = newContainer;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__CONTAINER, oldContainer, container));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public double getScalingFactor() {
return scalingFactor;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setScalingFactor(double newScalingFactor) {
double oldScalingFactor = scalingFactor;
scalingFactor = newScalingFactor;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__SCALING_FACTOR, oldScalingFactor, scalingFactor));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean isFit() {
return fit;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setFit(boolean newFit) {
boolean oldFit = fit;
fit = newFit;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__FIT, oldFit, fit));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean isEnforceContainment() {
return enforceContainment;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setEnforceContainment(boolean newEnforceContainment) {
boolean oldEnforceContainment = enforceContainment;
enforceContainment = newEnforceContainment;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__ENFORCE_CONTAINMENT, oldEnforceContainment, enforceContainment));
}
public IProject getProject() {
return project;
}
public void setProject(IProject p) {
this.project = p;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__DATA_FILE_NET:
return getDataFile_net();
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__AREA:
return getArea();
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__CONTAINER:
return getContainer();
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__SCALING_FACTOR:
return getScalingFactor();
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__FIT:
return isFit();
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__ENFORCE_CONTAINMENT:
return isEnforceContainment();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__DATA_FILE_NET:
setDataFile_net((String)newValue);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__AREA:
setArea((Double)newValue);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__CONTAINER:
setContainer((URI)newValue);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__SCALING_FACTOR:
setScalingFactor((Double)newValue);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__FIT:
setFit((Boolean)newValue);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__ENFORCE_CONTAINMENT:
setEnforceContainment((Boolean)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__DATA_FILE_NET:
setDataFile_net(DATA_FILE_NET_EDEFAULT);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__AREA:
setArea(AREA_EDEFAULT);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__CONTAINER:
setContainer(CONTAINER_EDEFAULT);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__SCALING_FACTOR:
setScalingFactor(SCALING_FACTOR_EDEFAULT);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__FIT:
setFit(FIT_EDEFAULT);
return;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__ENFORCE_CONTAINMENT:
setEnforceContainment(ENFORCE_CONTAINMENT_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__DATA_FILE_NET:
return DATA_FILE_NET_EDEFAULT == null ? dataFile_net != null : !DATA_FILE_NET_EDEFAULT.equals(dataFile_net);
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__AREA:
return area != AREA_EDEFAULT;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__CONTAINER:
return CONTAINER_EDEFAULT == null ? container != null : !CONTAINER_EDEFAULT.equals(container);
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__SCALING_FACTOR:
return scalingFactor != SCALING_FACTOR_EDEFAULT;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__FIT:
return fit != FIT_EDEFAULT;
case GraphgeneratorsPackage.PAJEK_NET_GRAPH_GENERATOR__ENFORCE_CONTAINMENT:
return enforceContainment != ENFORCE_CONTAINMENT_EDEFAULT;
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (dataFile_net: ");
result.append(dataFile_net);
result.append(", area: ");
result.append(area);
result.append(", container: ");
result.append(container);
result.append(", scalingFactor: ");
result.append(scalingFactor);
result.append(", fit: ");
result.append(fit);
result.append(", enforceContainment: ");
result.append(enforceContainment);
result.append(')');
return result.toString();
}
/**
* Import PajekNets into Graphs
* for Pajek format see: http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/pajekman.pdf
*
* we use compatible definitions of the pajek format only, which is:
* Vertices: vertexNumber label x y - the first 4 parameters are mandatory
* Arcs: v1 v2 value - all three parameters are mandatory
*
* Data File: Pajek file to import
* Area: Default Area of each node if undefined
*
*/
@Override
public Graph getGraph() {
Graph g = null;
File file = new File(getDataFile_net());
if (file != null && !file.isDirectory() && file.exists()) g = getGraph(file);
else Activator.logError("Pajek importing: File cannot be found", null);
return g;
}
private Graph getGraph(File pajekNETFileURI) {
final Graph graph = GraphFactory.eINSTANCE.createGraph();
final DublinCore dc = graph.getDublinCore();
dc.populate();
dc.setTitle("Pajek Import");
dc.setSource(this.getClass().getSimpleName());
Calendar c = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
String valid = formatter.format(c.getTime());
dc.setValid(valid);
List<LinkedHashMap<String, Double>> vPopulationListNodes = new ArrayList<LinkedHashMap<String, Double>>();
List<EdgeContainer> edgeContainerList = new ArrayList<EdgeContainer>();
Node nodeHolder[] = new Node[0];
Scanner input;
try {
input = new Scanner(pajekNETFileURI);
boolean doNodes = false, doEdges = false;
int numNodes = 0;
String nodeName[] = new String[0];
while(input.hasNext()) {
String nextLine = input.nextLine();
StreamTokenizer tok = new StreamTokenizer(new StringReader(nextLine.trim()));
tok.parseNumbers();
tok.wordChars('_','_'); // otherwise s_size wouldn't be detected
int ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
// e.g. Vertices 26
if (tok.sval.equalsIgnoreCase("vertices")) {
doNodes = true;
doEdges = false;
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
numNodes = (int) tok.nval;
nodeHolder = new Node[numNodes];
nodeName = new String[numNodes];
numNodes = 0;
}
else {
Activator.logError("Pajek importing " + pajekNETFileURI.getName() + ": vertices keyword without valid number of nodes... Not processable!", null);
input.close();
return null;
}
}
else if (tok.sval.equalsIgnoreCase("arcs") || tok.sval.equalsIgnoreCase("arcslist") || tok.sval.equalsIgnoreCase("edges")) {
doNodes = false;
doEdges = true;
}
else {
doNodes = false;
doEdges = false;
}
}
else if (doNodes && ttype == StreamTokenizer.TT_NUMBER) { // Nodes = Vertices
// default values
double x = 0, y = 0, z = 0;
String shape = "box";
double nodeArea = 0;
Color shapeColor = null;
LinkedHashMap<String, Double> vPopulation = new LinkedHashMap<String, Double>();
String populationIdentifier = "";
String parameter;
// vertex/node number
if (tok.nval != numNodes+1) {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": usually successive numbering of vertices/nodes... Please check! Exiting!", null);
input.close();
return null;
}
else {
nodeName[numNodes] = ""+(int)tok.nval;
}
// label
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD || ttype == '"') nodeName[numNodes] = tok.sval;
else if (ttype == StreamTokenizer.TT_NUMBER) {
nodeName[numNodes] = ""+(int)tok.nval;
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": a label for the node/vertex is obligatory... Exiting!", null);
input.close();
return null;
}
// coordinates of vertex/node, at least x and y, z is not used at the moment
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
x = tok.nval;
}
/*
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": coordinates for the node/vertex are necessary... Exiting!", null);
input.close();
return null;
}
*/
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
y = tok.nval;
}
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
z = tok.nval;
}
else {
tok.pushBack();
}
// shape
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
parameter = tok.sval.toLowerCase();
if (parameter.equals("ellipse") || parameter.equals("box") || parameter.equals("diamond") || parameter.equals("triangle") || parameter.equals("cross") || parameter.equals("empty")) {
shape = parameter;
}
else {
tok.pushBack();
}
}
/* other interesting parameters:
- s_size - default size
- bc - boundary color of vertex
*/
while(ttype != StreamTokenizer.TT_EOF) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
parameter = tok.sval.toLowerCase();
if (parameter.equals("s_size")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
nodeArea = tok.nval;
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": size of node has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("bc")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
shapeColor = getColor(tok.sval);
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": shapeColor value has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("popcount")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
//populationCount = tok.nval;
vPopulation.put(populationIdentifier, tok.nval);
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": popCount value has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("popid")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
populationIdentifier = tok.sval;
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": popCount value has wrong format... Exiting!", null);
input.close();
return null;
}
}
else {
ttype = getNextToken(tok);
}
}
}
// Thats it. At the moment we are not interested in more parameters, maybe later...
// scale x,y,z by scaling factor
x *= this.getScalingFactor();
y *= this.getScalingFactor();
z *= this.getScalingFactor();
// Creating node:
final Region regionNode = createRegionNode("PAJNET;" + nodeName[numNodes] + ";", x, y, graph);
double area = (nodeArea > 0 ? nodeArea*this.getScalingFactor()*this.getScalingFactor() : getArea());
final AreaLabel areaLabel = LabelsFactory.eINSTANCE.createAreaLabel();
areaLabel.getCurrentAreaValue().setArea(area);
regionNode.getLabels().add(areaLabel);
final LatLong nodeSegments = createNodePolygon(x,y,area,shape);
final String spatialURIString = InlineLatLongDataProvider.createSpatialInlineURIString(nodeSegments);
regionNode.getDublinCore().setSpatial(spatialURIString);
nodeHolder[numNodes] = regionNode;
numNodes++;
//vPop
vPopulationListNodes.add(vPopulation);
}
//Edges
else if (doEdges && ttype == StreamTokenizer.TT_NUMBER) { // Edges = Arcs
int a, b = 0;
int borderLength = 0;
double[] migrationRates = new double[2];
migrationRates[0] = 0; migrationRates[1] = 0;
String populationIdentifier = "";
LinkedHashMap<String, double[]> vPopulation = new LinkedHashMap<String, double[]>();
Color edgeColor = null;
// initial vertex number
a = (int) tok.nval;
// terminal vertex number
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) b = (int) tok.nval;
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": wrong arcs format. Cannot identify terminal node with initial node " + a + " ... Exiting!", null);
input.close();
return null;
}
// value of arc from a to b, we interpret it as borderLength, usually in Pajek format it is thickness of arc
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
borderLength = (int) tok.nval;
}
else if (ttype == StreamTokenizer.TT_EOF) {
// borderLength is not defined ; no problem for MigrationEdges
}
else {
tok.pushBack();
/*
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": wrong arcs format. Cannot identify value of arc between node " + a + " and node " + b + " ... Exiting!", null);
input.close();
return null;
*/
}
if (borderLength < 0) borderLength *= -1;
while(ttype != StreamTokenizer.TT_EOF) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
String parameter = tok.sval.toLowerCase();
if (parameter.equals("c")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
edgeColor = getColor(tok.sval);
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": color of edge has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("rateab")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
//migrationRateAB = tok.nval;
migrationRates[0] = tok.nval;
vPopulation.put(populationIdentifier, migrationRates);
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": migration rate AB of edge has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("rateba")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_NUMBER) {
//migrationRateBA = tok.nval;
migrationRates[1] = tok.nval;
vPopulation.put(populationIdentifier, migrationRates);
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": migration rate BA of edge has wrong format... Exiting!", null);
input.close();
return null;
}
}
else if (parameter.equals("popid")) {
ttype = getNextToken(tok);
if (ttype == StreamTokenizer.TT_WORD) {
populationIdentifier = tok.sval;
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": population identifier of edge has wrong format... Exiting!", null);
input.close();
return null;
}
}
}
}
//vPop
edgeContainerList.add(new EdgeContainer(a,b,borderLength,vPopulation));
}
else {
Activator.logError("Pajek importing: " + pajekNETFileURI.getName() + ": very special Pajek format?!? Not processable!", null);
input.close();
return null;
}
} //input has next
input.close();
}
catch (Exception e) {
e.printStackTrace();
}
processNodes(graph, nodeHolder);
//nodes
for (int i=0; i<nodeHolder.length; i++)
{ //System.err.println("node " + i + ": URI: "+ nodeHolder[i].getURI());
Map<String, Double> vPopulation = vPopulationListNodes.get(i);
if (vPopulationListNodes.get(i) != null)
//System.err.println("vPop node size: " + vPopulationListNodes.get(i).size());
for (Map.Entry<String, Double> entry : vPopulation.entrySet()) {
String populationID = entry.getKey();
if (populationID.length() > 0) {
double populationCount = entry.getValue();
// Create a new population label
PopulationLabel newLabel = LabelsFactory.eINSTANCE.createPopulationLabel();
newLabel.setPopulationIdentifier(populationID);
newLabel.setURIOfIdentifiableToBeLabeled(nodeHolder[i].getURI());
newLabel.setNode(nodeHolder[i]);
URI newURI = createPopulationLabelURI(nodeHolder[i], populationID);
//graph.getNodeLabels().put(newURI, newLabel);
initializeLabel(newLabel, populationID, populationCount);
}
}
graph.putNode(nodeHolder[i]);
}
//edges
for (EdgeContainer edgeContainer : edgeContainerList)
{
int a = edgeContainer.a;
int b = edgeContainer.b;
int borderLength = edgeContainer.borderLength;
LinkedHashMap<String, double[]> vPopulation = edgeContainer.vPopulation;
if (vPopulation.size() == 0) {
createCommonBorderEdge(graph,nodeHolder[a-1],nodeHolder[b-1], borderLength);
}
else {
for (Map.Entry<String, double[]> entry : vPopulation.entrySet()) {
String populationID = entry.getKey();
if (populationID.length() > 0) {
double[] migrationRates = entry.getValue();
createMigrationEdge(graph,nodeHolder[a-1],nodeHolder[b-1], entry.getKey(), migrationRates[0], migrationRates[1]);
}
}
}
}
assert graph.sane();
return graph;
}
//#########################################################################################
private void processNodes(Graph graph, Node[] nodeHolder)
{
if (this.getContainer() != null) {
URI containerURI = this.getContainer();
//bug.. removed.
if (containerURI.toString().lastIndexOf("stem://org.eclipse.stem/") !=
containerURI.toString().indexOf("stem://org.eclipse.stem/"))
{ containerURI = URI.createURI(containerURI.toString().substring(24)); }
//spatial information of containing node
Set<LatLong> spatialsList = getSpatials(project, containerURI);
// Fit=true: only create containment edges if pajek node is within a containment area
if (this.isFit() == true)
{
//fit graph into area
fitPajekIntoContainingNode(nodeHolder, spatialsList);
//now all nodes of the graph are contained with in the containing area
for (int i=0; i<nodeHolder.length; i++)
{ setContainedNodeURI(containerURI,nodeHolder[i]);
createContainmentEdge(graph, containerURI, nodeHolder[i]);
}
}
else { //Fit=false,
//containment edges will be set if pajek node lies in containing area
if (isEnforceContainment())
{
for (int i=0; i<nodeHolder.length; i++)
{
setContainedNodeURI(containerURI,nodeHolder[i]);
createContainmentEdge(graph, containerURI, nodeHolder[i]);
}
}
else
{
boolean[] node_fit = new boolean[nodeHolder.length];
java.util.Arrays.fill(node_fit,true);
int nodecnt=0;
for (int i=0; i<nodeHolder.length; i++) //pajek nodes
{
LatLongProvider latLongProvider = (LatLongProvider) LatLongProviderAdapterFactory.INSTANCE
.adaptNew(nodeHolder[i], LatLongProvider.class);
//pajekSpatialsList.add(latLongProvider.getLatLong());
LatLong pajekSpatial = latLongProvider.getLatLong();
for (Segment pajekSubspatial : pajekSpatial.getSegments())
{ // size of one usually as one pajek node has only one shape
//shape_fit: stores whether segment coordinates are within containing polygon or not
boolean[] shape_fit = new boolean[pajekSubspatial.size()];
java.util.Arrays.fill(shape_fit,false); //anyway
for (LatLong spatials : spatialsList)
{
List<Segment> subspatials = spatials.getSegments();
for (Segment subspatial : subspatials) {
for (int z=0; z < pajekSubspatial.size(); z++) {
if(containsPoint(pajekSubspatial.latitude(z),pajekSubspatial.longitude(z),subspatial))
{ //if one point of the pajek node (box, ellipse) is within one of containing node areas, set true
shape_fit[z] = true;
}
} // test: coordinates of pajek nodes in containing area?
} // different locations (gml:pos) of containing node (islands..)
} // containing node(s)
for (int shapefitidx = 0; shapefitidx < shape_fit.length; shapefitidx++)
if (shape_fit[shapefitidx] == false) node_fit[nodecnt]=false;
} // Pajek segment(s)
//when a segment coordinates of the pajek node did not fit into the coordinate polygon
//of containung node, this node will not get a containment edge
if (node_fit[nodecnt]==true)
{
setContainedNodeURI(containerURI,nodeHolder[nodecnt]);
createContainmentEdge(graph, containerURI, nodeHolder[nodecnt]);
}
nodecnt++;
} // Pajek nodes (PajekSpatialsList)
} //end if-else (containment)
} // if-else (fit)
}
}
private void setContainedNodeURI(URI containerURI, Node node)
{
URI nodeURI = node.getURI().trimFragment();
String base= nodeURI.toString().substring(0, nodeURI.toString().lastIndexOf("/")+1);
node.setURI(URI.createURI(base + containerURI.lastSegment()+"-"+nodeURI.lastSegment()));
}
private int getNextToken(StreamTokenizer tok) throws IOException {
int ttype = 0;
while((ttype = tok.nextToken()) != StreamTokenizer.TT_WORD && ttype != StreamTokenizer.TT_NUMBER && ttype != StreamTokenizer.TT_EOF && ttype != '"') {
;
}
return ttype;
}
private Color getColor(String strColor) {
String c = strColor.toLowerCase();
if (c.equals("black")) return Color.BLACK;
else if (c.equals("blue")) return Color.BLUE;
else if (c.equals("cyan")) return Color.CYAN;
else if (c.equals("gray")) return Color.GRAY;
else if (c.equals("green")) return Color.GREEN;
else if (c.equals("magenta")) return Color.MAGENTA;
else if (c.equals("orange")) return Color.ORANGE;
else if (c.equals("pink")) return Color.PINK;
else if (c.equals("red")) return Color.RED;
else if (c.equals("white")) return Color.WHITE;
else if (c.equals("yellow")) return Color.YELLOW;
else return Color.BLACK;
}
/**
*
* @param x
* @param y
* @param area
* @return
*/
private LatLong createNodePolygon(final double x, double y, double area, String shape) {
final LatLong retValue = new LatLong();
final SegmentBuilder sb = new SegmentBuilder();
// ellipse box diamond triangle cross empty
if (shape.toLowerCase().equals("triangle")) {
double areax2 = Math.sqrt(4 * area / Math.sqrt(3)) / 2;
double areay = areax2 / Math.sqrt(3);
sb.add(x-areax2, y-areay);
sb.add(x+areax2, y-areay);
sb.add(x, y+2*areay);
sb.add(x-areax2, y-areay);
}
else if (shape.toLowerCase().equals("cross")) {
double area2 = Math.sqrt(2 * area / Math.sqrt(3)) / 2;
sb.add(x+area2, y+area2);
sb.add(x-area2, y-area2);
sb.add(x-area2, y+area2);
sb.add(x+area2, y-area2);
sb.add(x+area2, y+area2);
}
else if (shape.toLowerCase().equals("ellipse")) { // circle
double r = Math.sqrt(area / Math.PI);
int numSegs = 20;
for (int i=0;i<=numSegs;i++) {
sb.add(x + r * Math.cos(2*Math.PI*i/numSegs), y + r * Math.sin(2*Math.PI*i/numSegs));
}
}
else { // box,diamond,empty,default
double area2 = Math.sqrt(area) / 2;
// We just make a square...
sb.add(x-area2, y-area2);
sb.add(x-area2, y+area2);
sb.add(x+area2, y+area2);
sb.add(x+area2, y-area2);
sb.add(x-area2, y-area2);
}
retValue.add(sb.toSegment());
return retValue;
} // createNodePolygon
/**
* @param x
* the x coord of the node in the lattice
* @param y
* the y coord of the node in the lattice
* @return a node
*/
private Region createRegionNode(String uriPrefix, double x, double y, Graph graph) {
final Region node = NodesFactory.eINSTANCE.createRegion();
final DublinCore dc = node.getDublinCore();
dc.setTitle(createNodeTitle(x, y));
node.setURI(createRegionNodeURI(uriPrefix, x, y, graph));
return node;
} // createRegionNode
/**
* @param x
* the x of the node in the lattice
* @param y
* the y of the node in the lattice
* @return a title for a node
*/
private String createNodeTitle(double x, double y) {
final StringBuilder sb = new StringBuilder("Node[");
sb.append(String.valueOf(((long)(x*100))/100));
sb.append(", ");
sb.append(String.valueOf(((long)(y*100))/100));
sb.append("]");
return sb.toString();
} // createNodeTitle
/**
* @param x
* the x of the region in the lattice
* @param y
* the y of the region in the lattice
* @return a URI for the region node
*/
private URI createRegionNodeURI(String uriPrefix, double x, double y, Graph graph) {
String nodeUriSuffix = uriPrefix+
String.valueOf(((long)(x*100))/100)
+
";"
+
String.valueOf(((long)(y*100))/100);
String nodeUriString = Node.URI_TYPE_NODE_SEGMENT + "/"
+ graph.getURI().lastSegment()+"/"
+ nodeUriSuffix;
URI uri = STEMURI.createURI(nodeUriString);
return uri;
} // createRegionNodeURI
/**
*
* @param graph
* @param nodeA
* @param nodeB
* @param borderLength
*/
private void createCommonBorderEdge(final Graph graph, final Node nodeA, final Node nodeB, int borderLength) {
// create the edge
final Edge edge = CommonBorderRelationshipLabelImpl.createCommonBorderRelationship(nodeA, nodeB, borderLength);
URI edgeURI = edge.getURI();
// the autogenerated edge uri is not correct. Need to replace it
String sEdge = edgeURI.toString();
int last = sEdge.lastIndexOf("/");
String sEdge1 = sEdge.substring(0,last);
String sEdge2 = sEdge.substring(last,sEdge.length());
sEdge = sEdge1+"/relationship/commonborder"+sEdge2;
URI newURI = URI.createURI(sEdge);
edge.setURI(newURI);
// now we need to set the uri for the label
CommonBorderRelationshipLabel label = (CommonBorderRelationshipLabel)edge.getLabel();
label.setURI(createEdgeLabelURI(nodeA.getURI(), nodeB.getURI()));
final DublinCore dc = edge.getDublinCore();
dc.setTitle(createEdgeTitle(nodeA, nodeB));
graph.putEdge(edge);
} // createCommonBorderEdge
/**
* @param x
* the x of the node in the lattice
* @param y
* the y of the node in the lattice
* @return a title for a node
*/
private String createEdgeTitle(Node nodeA, Node nodeB) {
String nA = nodeA.getDublinCore().getTitle();
String nB = nodeB.getDublinCore().getTitle();
final StringBuilder sb = new StringBuilder("Edge[(");
sb.append(nA);
sb.append(")<-->(");
sb.append(nB);
sb.append(")]");
return sb.toString();
} // createEdgeTitle
/**
*
* @param uriA
* @param uriB
* @return
*/
private static URI createEdgeLabelURI(URI uriA, URI uriB) {
String sA = uriA.lastSegment();
String sB = uriB.lastSegment();
// MigrationEdgeLabelItemProvider
// uses _ as a special character to separate the two nodes
// so we need to replace it.
sA=sA.replace('_','.');
sB=sB.replace('_','.');
String uriString = sA+"_"+sB;
//System.out.println("createEdgeLabelURI() : FINALLY, uri = "+uriString);
URI uri = STEMURI.createURI(uriString);
return uri;
} // createEdgeLabelURI
private void createMigrationEdge(final Graph graph, final Node nodeA, final Node nodeB, String populationIdentifier, double migrationRateAB, double migrationRateBA) {
URI sourceURI = nodeA.getURI();
URI targetURI = nodeB.getURI();
EdgesFactory ef = EdgesFactoryImpl.init();
MigrationEdge mEdge1 = ef.createMigrationEdge();
MigrationEdge mEdge2 = ef.createMigrationEdge();
// The URI of the edge 1
URI edgeURI1 = mEdge1.getURI();
// the autogenerated edge uri is not correct. Need to replace it
String s1 = edgeURI1.toString();
int last = s1.lastIndexOf("/");
String sEdge1 = s1.substring(0,last);
String sEdge2 = s1.substring(last,s1.length());
s1 = sEdge1+"/relationship/migration"+sEdge2;
URI newURI = URI.createURI(s1);
mEdge1.setURI(newURI);
// The URI of the edge 2
URI edgeURI2 = mEdge2.getURI();
// the autogenerated edge uri is not correct. Need to replace it
String s2 = edgeURI2.toString();
int last2 = s2.lastIndexOf("/");
sEdge1 = s2.substring(0,last2);
sEdge2 = s2.substring(last,s2.length());
s2 = sEdge1+"/relationship/migration"+sEdge2;
URI newURI2 = URI.createURI(s2);
mEdge2.setURI(newURI2);
// ADD The URIs of the nodes connected by these two directed edges
// A => B
mEdge1.setNodeAURI(sourceURI);
mEdge1.setNodeBURI(targetURI);
// B => A
mEdge2.setNodeBURI(sourceURI);
mEdge2.setNodeAURI(targetURI);
// now we need to set the uri for the label
MigrationEdgeLabel label1 = mEdge1.getLabel();
MigrationEdgeLabel label2 = mEdge2.getLabel();
//System.out.println("BEFORE: mEdgeLabel1 URI was "+label1.getURI().toString());
//System.out.println("BEFORE: mEdgeLabel2 URI was "+label2.getURI().toString());
label1.setURI(createEdgeLabelURI(sourceURI, targetURI));
label2.setURI(createEdgeLabelURI(targetURI, sourceURI));
MigrationEdgeLabelValue melv1 = label1.getCurrentValue();
melv1.setMigrationRate(migrationRateAB);
MigrationEdgeLabelValue melv2 = label2.getCurrentValue();
melv2.setMigrationRate(migrationRateBA);
final DublinCore dc1 = mEdge1.getDublinCore();
dc1.setTitle(createMigrationEdgeTitle(sourceURI, targetURI));
final DublinCore dc2 = mEdge2.getDublinCore();
dc2.setTitle(createMigrationEdgeTitle(targetURI, sourceURI));
mEdge1.setPopulationIdentifier(populationIdentifier);
mEdge2.setPopulationIdentifier(populationIdentifier);
graph.putEdge(mEdge1);
graph.putEdge(mEdge2);
}
/**
* @param x
* the x of the node in the lattice
* @param y
* the y of the node in the lattice
* @return a title for a node
*/
public static String createMigrationEdgeTitle(URI uriA, URI uriB) {
String sA = uriA.lastSegment();
String sB = uriB.lastSegment();
final StringBuilder sb = new StringBuilder("MigrationEdge[(");
sb.append(sA);
sb.append(")<-->(");
sb.append(sB);
sb.append(")]");
return sb.toString();
} // createEdgeTitle
private URI createPopulationLabelURI(Node n, String population) {
int adminLevel = Utility.keyLevel(n.getURI().lastSegment());
String countryCode = getCountryCode(n);
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
String code = n.getURI().lastSegment();
return PopulationLabelImpl.createPopulationLabelURI(adminLevel, countryCode, population, year+"", code);
}
private String getCountryCode(Node n) {
if(Utility.keyLevel(n.getURI().lastSegment()) == 0) return n.getURI().lastSegment();
else for(Edge e:n.getEdges())
if(Utility.keyLevel(e.getA().getURI().lastSegment()) < Utility.keyLevel(n.getURI().lastSegment()))
return getCountryCode(e.getA());
return "ZZZ"; // Not found, but ZZZ is the parent of everything
}
private void initializeLabel(PopulationLabel lab, String populationIdentifier, double populationCount) {
PopulationLabelValue plv = lab.getCurrentPopulationValue();
plv.setCount(populationCount);
// Set the valid year to the start year of the sequencer
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
lab.setValidYear(year);
}
private void createContainmentEdge(final Graph graph, final URI URIA, final Node nodeB ) {
final Edge cEdge = EdgeImpl.createEdge(URIA, nodeB.getURI());
final RelativePhysicalRelationshipLabel containLabel = LabelsFactory.eINSTANCE
.createRelativePhysicalRelationshipLabel();
containLabel.setURIOfIdentifiableToBeLabeled(cEdge.getURI());
containLabel.getCurrentRelationship().setRelationship(
RelativePhysicalRelationship.CONTAINS_LITERAL);
final RelativePhysicalRelationshipLabelValue currentValue = LabelsFactory.eINSTANCE
.createRelativePhysicalRelationshipLabelValue();
currentValue.setAdjacent(false);
currentValue
.setRelationship(RelativePhysicalRelationship.CONTAINS_LITERAL);
containLabel.setCurrentValue(currentValue);
cEdge.setDirected(true);
String nodeAURIfull = URIA.toString();
int lastA = nodeAURIfull.lastIndexOf("/")+1;
String nodeAURI = nodeAURIfull.substring(lastA,nodeAURIfull.length());
String nodeBURIfull = nodeB.getURI().toString();
int lastB = nodeBURIfull.lastIndexOf("/")+1;
String nodeBURI = nodeBURIfull.substring(lastB,nodeBURIfull.length());
// create the uri;
final StringBuilder sb = new StringBuilder(
"edge/relationship/relativephysical/"); //$NON-NLS-1$
sb.append(nodeAURI);
sb.append("_"); //$NON-NLS-1$
sb.append(nodeBURI);
sb.append("/"); //$NON-NLS-1$
sb.append(RelativePhysicalRelationship.CONTAINS_LITERAL.toString()
.toLowerCase());
cEdge.setURI(STEMURI.createURI(sb.toString()));
containLabel.setURI(STEMURI.createURI(sb.toString()));
cEdge.setLabel(containLabel);
containLabel.setURIOfIdentifiableToBeLabeled(cEdge.getURI());
cEdge.getDublinCore().setTitle(nodeB.getURI().lastSegment());
graph.putEdge(cEdge);
} // createContainmentEdge
public boolean containsPoint(double x, double y, Segment datapoints) {
int i, j;
boolean isInside = false;
double[] points = new double[2*datapoints.size()];
for (int k = 0, pointsIndex = 0; k < datapoints.size(); k++, pointsIndex+=2) {
points[pointsIndex] = datapoints.latitude(k);
points[pointsIndex+1] = datapoints.longitude(k);
}
int numOfPoints = points.length/2;
for (i = 0, j = (numOfPoints-1)*2; i < points.length-1; ) {
if ((((points[i+1]<=y) && (y<points[j+1])) ||
((points[j+1]<=y) && (y<points[i+1]))) &&
(x < (points[j] - points[i]) * (y - points[i+1]) / (points[j+1] - points[i+1]) + points[i])) {
isInside = !isInside;
}
j = i;
i += 2;
}
return isInside;
}
public static Set<LatLong> getSpatials(IProject project, URI location) {
//U
Map<String,LatLong> latLongs = new HashMap<String,LatLong>();
if (project != null)
{
IContainer modelFolder = project.getFolder("models");
IResource[] models = null;
try {
models = modelFolder.members();
} catch(Exception e) {
e.printStackTrace();
}
if (models != null) {
for(IResource r:models) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
Graph g = ((Model)id).getCanonicalGraph(STEMURI.createURI(""), null, null);
if(id instanceof Model) latLongs.putAll(getGraphSpatials(g, location));
} catch(Exception e) {
// Skip bad file
}
}
}
IContainer graphsFolder = project.getFolder("graphs");
IResource[] graphs = null;
try {
graphs = graphsFolder.members();
} catch(Exception e) {
e.printStackTrace();
}
if (graphs != null) {
for(IResource r:graphs) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
if(id instanceof Graph) latLongs.putAll(getGraphSpatials((Graph)id, location));
} catch(Exception e) {
// Skip bad file
}
}
}
}
Set<LatLong> retVal = new HashSet<LatLong>();
retVal.addAll(latLongs.values());
return retVal;
}
private static Map<String,LatLong> getGraphSpatials(Graph g, URI location) {
Map<String,LatLong> latlongs = new HashMap<String,LatLong>();
for(Node n: g.getNodes().values()) {
URI uriKey = n.getURI();
//get spatial information of containing node
if(location != null && !location.toString().trim().equals(""))
{
//TODO make check for entire URI instead of last segment? (when bug with wrong getContainer URI is fixed)
//if (uriKey.lastSegment().equals(location.lastSegment()))
if (uriKey.toString().equals(location.toString()))
{
//URI spatialURI = URI.createURI(n.getDublinCore().getSpatial().replace("stemspatial:",""));
final LatLongProvider latLongProvider = (LatLongProvider) LatLongProviderAdapterFactory.INSTANCE
.adapt(n, LatLongProvider.class);
final LatLong result = latLongProvider.getLatLong();
latlongs.put(uriKey.toString(), result);
}
}
}
return latlongs;
}//getGraphSpatials
private static void fitPajekIntoContainingNode(Node[] nodeHolder, Set<LatLong> spatialsList )
{
// not optimal, as is takes largest area and fits into this.
// problem in case of island countries,
// where different pajek nodes might be on different islands
//spatial information of pajek graph nodes
Set<LatLong> pajekSpatialsList = new HashSet<LatLong>();
for (int nodeidx=0; nodeidx<nodeHolder.length; nodeidx++)
{
LatLongProvider latLongProvider = (LatLongProvider) LatLongProviderAdapterFactory.INSTANCE
.adaptNew(nodeHolder[nodeidx], LatLongProvider.class);
pajekSpatialsList.add(latLongProvider.getLatLong());
}
if ( (spatialsList.size() == 0) || pajekSpatialsList.size() == 0) // || (graph==null) )
return;
double largestArea = -1.0;
Polygon pajekNodePoly, pajekPoly, newContainingPoly=null;
//get largest area of the containing area node and its center
for (LatLong spatials : spatialsList)
{
List<Segment> subspatials = spatials.getSegments();
for (Segment subspatial : subspatials)
{
Polygon poly = getPolygon(subspatial);
double area = Math.abs(getArea(poly));
if(area >= largestArea) {
largestArea = area;
//already rescaled:
newContainingPoly = new Polygon(poly.xpoints, poly.ypoints, poly.npoints);
}
}
}
Point containingCenter = getInteriorCentroid(newContainingPoly);
//get center of entire pajek polygon
SegmentBuilder sb = new SegmentBuilder();
double maxLat=Double.NEGATIVE_INFINITY,
maxLong=Double.NEGATIVE_INFINITY,
minLat=Double.MAX_VALUE,
minLong=Double.MAX_VALUE;
for (LatLong pajekSpatial : pajekSpatialsList) //nodes
{
for (Segment pajekSubspacial : pajekSpatial.getSegments()) //usually size 1
{ //this made problems with Polygon functions, now old fashioned way
for (int z=0; z < pajekSubspacial.size(); z++) {
minLat = (pajekSubspacial.latitude(z) < minLat)? pajekSubspacial.latitude(z) : minLat ;
maxLat = (pajekSubspacial.latitude(z) > maxLat)? pajekSubspacial.latitude(z) : maxLat ;
minLong = (pajekSubspacial.longitude(z) < minLong) ? pajekSubspacial.longitude(z) :minLong ;
maxLong = (pajekSubspacial.longitude(z) > maxLong) ? pajekSubspacial.longitude(z) :maxLong ;
}
}
}
sb.add(minLat,minLong);
sb.add(minLat+(maxLat-minLat),minLong);
sb.add(minLat,minLong+(maxLong-minLong));
sb.add(minLat+(maxLat-minLat),minLong);
sb.add(minLat+(maxLat-minLat), minLong+(maxLong-minLong) );
sb.add(minLat,minLong);
pajekPoly = getPolygon(sb.toSegment());
Point pajekCenter = getInteriorCentroid(pajekPoly);
//get minimal distance between center of containing area and border
double minDist = Double.MAX_VALUE;
for (int i=0; i<newContainingPoly.npoints; i++)
{
double dist = Math.sqrt(
Math.pow(newContainingPoly.xpoints[i] - containingCenter.x, 2.0)
+
Math.pow(newContainingPoly.ypoints[i] - containingCenter.y, 2.0)
);
if (dist < minDist) minDist = dist;
}
//get maximal distance between center of pajek polygon and border
double maxDist = Double.NEGATIVE_INFINITY;
for (LatLong pajekSpatial : pajekSpatialsList) //nodes
{
for (Segment pajekSubspatial : pajekSpatial.getSegments()) //usually size 1
{
pajekNodePoly = getPolygon(pajekSubspatial);
for (int i=0; i<pajekNodePoly.npoints; i++)
{
double dist = Math.sqrt(
Math.pow(pajekNodePoly.xpoints[i] - pajekCenter.x, 2.0)
+
Math.pow(pajekNodePoly.ypoints[i] - pajekCenter.y, 2.0)
);
if (dist > maxDist) maxDist = dist;
}
}
}
//TODO: exagerrated, just to make sure it fits
maxDist += Math.sqrt( Math.pow(pajekPoly.getBounds().getWidth()/2, 2) + Math.pow(pajekPoly.getBounds().getHeight()/2, 2));
/*System.err.println("Containing Center: " +containingCenter );
System.err.println("Containing Center: " +pajekCenter);
System.err.println("maxDist: " + maxDist);
System.err.println("minDist: " + minDist);
*/
//transform
LatLong transformedNodes = new LatLong();
double factor = maxDist / minDist;
double xtrans = (pajekCenter.x / factor) - containingCenter.x;
double ytrans = (pajekCenter.y / factor) - containingCenter.y;
for (Node n: nodeHolder)
{
LatLongProvider latLongProvider = (LatLongProvider) LatLongProviderAdapterFactory.INSTANCE
.adaptNew(n, LatLongProvider.class);
LatLong pajekSpacial = latLongProvider.getLatLong();
for (Segment segment : pajekSpacial.getSegments()) //usually size 1
{
pajekNodePoly = getPolygon(segment);
sb = new SegmentBuilder();
for (int i=0; i< segment.size(); i++)
{
double xnew = (segment.latitude(i) / factor) - xtrans/RESCALE;
double ynew = (segment.longitude(i) / factor) - ytrans/RESCALE;
sb.add(xnew, ynew);
}
transformedNodes = new LatLong();
transformedNodes.add(sb.toSegment());
//TODO here, the inline string cuts off after two digits.. graphics/spatials are scrambled
n.getDublinCore().
setSpatial(InlineLatLongDataProvider.createSpatialInlineURIString(transformedNodes));
for (NodeLabel label : n.getLabels())
{
if (label instanceof AreaLabel)
{
double area = ((AreaLabel)label).getCurrentAreaValue().getArea();
area /= Math.pow(factor, 2);
area = ((long)(area*100000));
area /= 100000;
((AreaLabel)label).getCurrentAreaValue().setArea(area);
}
}
}
} //end nodes transform
} //end of fitPajekIntoContainingNode
private static Polygon getPolygon(Segment segment)
{
int size = segment.size();
int[] lt = new int[size];
int[] lg = new int[size];
for (int i = 0; i < size; i ++) {
if ((segment.latitude(i)*RESCALE > Integer.MAX_VALUE) ||
(segment.latitude(i)*RESCALE > Integer.MAX_VALUE))
Activator.logError("Coordinate range too large... Exiting!", null);
lt[i] = (int) (segment.latitude(i)*RESCALE );
lg[i] = (int) (segment.longitude(i)*RESCALE );
}
// check if it is a polygon, repair if necessary
if(!(size > 2 && lt[0] == lt[size-1] && lg[0] == lg[size - 1]
))
{
if (size > 2) {
size++;
int[] lt_new = new int[size];
int[] lg_new = new int[size];
for (int i=0; i<size-1; i++)
{
lt_new[i] = lt[i];
lg_new[i] = lg[i];
}
lt_new[size-1] = lt[0];
lg_new[size-1] = lg[0];
if(size > 2 && lt_new[0] == lt_new[size-1] && lg_new[0] == lg_new[size - 1])
return new Polygon(lt_new, lg_new, size);
}
else
{
Activator.logError("Returned null Polygon pointer", null);
return null;
}
}
return new Polygon(lt, lg, size);
}
public static double getArea(Polygon p) {
double area = 0;
int[] x = p.xpoints;
int[] y = p.ypoints;
for (int i = 0; i < x.length-1; i ++) {
area += (((double)x[i]*(double)y[i+1]) - ((double)x[i+1]*(double)y[i]));
}
area /= 2.0;
return area>0?area:-area;
}
public static Point getInteriorCentroid(Polygon p) {
double maxRange = -1.0;
double cx = 0;
double cy = 0;
Rectangle r = p.getBounds();
final double STEP = 100.0;
double deltax = Math.abs((double) r.width);
double deltay = Math.abs((double) r.height);
deltax /= STEP;
deltay /= STEP;
double x = r.getMinX();
double y = r.getMinY();
for (int i = 0; i <= (int) STEP; i ++) {
y = r.getMinY();
for(int j = 0; j <= (int)STEP; j ++) {
if(p.contains(x, y)) {
double range = getSqrdEdgeRange(x,y,p);
if (range >= maxRange) {
maxRange = range;
cx = x;
cy = y;
}
}
y += deltay;
}
x += deltax;
}
x = cx-deltax;
y = cy-deltay;
double y0 = y;
deltax /= STEP;
deltay /= STEP;
for (int i = 0; i <= (int)(2.0* STEP); i ++) {
y = y0;
for(int j = 0; j <= (int)(2.0*STEP); j ++) {
if(p.contains(x, y)) {
double range = getSqrdEdgeRange(x,y,p);
if (range >= maxRange) {
maxRange = range;
cx = x;
cy = y;
}
}
y += deltay;
}
x += deltax;
}
int ix = (int)Math.round(cx);
int iy = (int)Math.round(cy);
Point center = new Point(ix,iy);
return center;
}// end of get inner centroid
public static double getSqrdEdgeRange(double qx, double qy, Polygon p) {
double range = Double.MAX_VALUE;
int[] ix = p.xpoints;
int[] iy = p.ypoints;
for (int i=0;i<ix.length;i++) {
double x = ix[i];
double y = iy[i];
double dx = qx-x;
double dy = qy-y;
double r = (dx*dx) + (dy*dy);
if (r <= range) range = r;
}
return range;
}
public class EdgeContainer
{
int a;
int b;
int borderLength;
LinkedHashMap<String, double[]> vPopulation;
public EdgeContainer(int a, int b, int borderLength, LinkedHashMap<String, double[]> vPopulation)
{
this.a = a;
this.b = b;
this.borderLength = borderLength;
this.vPopulation = vPopulation;
}
}
} //PajekNetGraphGeneratorImpl