Skip to content

Commit

Permalink
✨ Added GraphWriter
Browse files Browse the repository at this point in the history
Fixes #17
  • Loading branch information
Komposten committed Jun 1, 2019
1 parent 192f81c commit f17c00c
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 2 deletions.
180 changes: 180 additions & 0 deletions core/src/komposten/tcs/backend/GraphWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package komposten.tcs.backend;

import java.io.File;
import java.io.IOException;
import java.util.Map.Entry;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector3;

import komposten.tcs.backend.Style.Colour;
import komposten.tcs.backend.Style.Setting;
import komposten.tcs.backend.data.GraphData;
import komposten.tcs.backend.data.Point;
import komposten.tcs.backend.data.PointGroup;
import komposten.tcs.backend.data.Volume;
import komposten.tcs.util.TCSUtils;
import komposten.utilities.tools.MathOps;


public class GraphWriter
{
/**
* Writes the specified {@link GraphData} to the specified file.
* @param graph The <code>GraphData</code> to save.
* @param style The graph's style.
* @param file The destination file.
* @throws IOException If the XML model could not be created or saved to the destination file.
*/
public void write(GraphData graph, Style style, File file) throws IOException
{
try
{
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Document doc = docBuilderFactory.newDocumentBuilder().newDocument();

Element dataElement = doc.createElement("data");
doc.appendChild(dataElement);

addStyleElement(style, doc, dataElement);
addPointElements(graph, style, doc, dataElement);
addVolumeElements(graph, doc, dataElement);

saveToFile(doc, file);
}
catch (ParserConfigurationException e)
{
throw new IOException("Could not configure the XML parser!", e);
}
}


private void addStyleElement(Style style, Document doc, Element parent)
{
if (!style.getChangedColours().isEmpty() || !style.getChangedSettings().isEmpty())
{
Element styleElement = doc.createElement("style");
parent.appendChild(styleElement);

for (Entry<Colour, Color> entry : style.getChangedColours().entrySet())
{
Element colourElement = doc.createElement("colour");
colourElement.setAttribute("id", entry.getKey().name().toLowerCase());
colourElement.setTextContent("#" + entry.getValue().toString());
styleElement.appendChild(colourElement);
}

for (Entry<Setting, Number> entry : style.getChangedSettings().entrySet())
{
Element settingElement = doc.createElement("setting");
settingElement.setAttribute("id", entry.getKey().name().toLowerCase());
settingElement.setTextContent(entry.getValue().toString());
styleElement.appendChild(settingElement);
}
}
}


private void addPointElements(GraphData graph, Style style, Document doc,
Element parent)
{
for (PointGroup group : graph.getDataGroups())
{
Element groupElement = doc.createElement("group");
groupElement.setAttribute("name", group.getName());
groupElement.setAttribute("shape", group.getShape().toString());

if (!MathOps.equals(group.getSize(), style.get(Setting.POINT_SIZE).floatValue(), 0.00001f))
groupElement.setAttribute("size", Float.toString(group.getSize()));

for (Point point : group.getPoints())
{
Element pointElement = doc.createElement("point");
pointElement.setAttribute("name", point.getName());
pointElement.setAttribute("colour", "#" + point.getColour().toString());
pointElement.setAttribute("position", vectorToString(point.getMetrics()));
groupElement.appendChild(pointElement);
}

parent.appendChild(groupElement);
}
}


private void addVolumeElements(GraphData graph, Document doc, Element parent)
{
for (Volume volume : graph.getDataVolumes())
{
Element volumeElement = doc.createElement("volume");
volumeElement.setAttribute("colour", "#" + volume.getColour().toString());
volumeElement.setTextContent(volumeToString(volume));

parent.appendChild(volumeElement);
}
}


private String vectorToString(Vector3 vector)
{
return String.format("%f,%f,%f", vector.x, vector.y, vector.z);
}


private String volumeToString(Volume volume)
{
StringBuilder builder = new StringBuilder();

double[] coords = volume.getCoordinates();
for (int i = 0; i < coords.length; i += 3)
{
Vector3 metrics = TCSUtils.getMetricsForCoordinates(
(float) coords[i], (float) coords[i + 1],
(float) coords[i + 2]);
builder.append(metrics.x).append(',')
.append(metrics.y).append(',')
.append(metrics.z).append('\n');
}

return builder.toString();
}


private void saveToFile(Document doc, File file) throws IOException
{
try
{
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(file);

transformer.transform(source, result);
}
catch (TransformerConfigurationException e)
{
throw new IOException("Could not create the XML transformer!", e);
}
catch (TransformerException e)
{
throw new IOException("Could not save the XML to " + file.getName() + "!", e);
}
}
}
46 changes: 44 additions & 2 deletions core/src/komposten/tcs/backend/Style.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@
package komposten.tcs.backend;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils;

import komposten.tcs.util.TCSUtils;
import komposten.utilities.tools.MathOps;
Expand Down Expand Up @@ -60,6 +63,9 @@ public enum Setting

private Map<Colour, Color> colours;
private Map<Setting, Number> settings;

private Set<Colour> isDefaultColour;
private Set<Setting> isDefaultSetting;

public Style()
{
Expand All @@ -71,6 +77,8 @@ public Style()
{
colours = new EnumMap<>(Colour.class);
settings = new EnumMap<>(Setting.class);
isDefaultColour = EnumSet.noneOf(Colour.class);
isDefaultSetting = EnumSet.noneOf(Setting.class);

loadDefaults();
if (styleNode != null)
Expand Down Expand Up @@ -137,7 +145,15 @@ private void loadColour(String id, String value)
Colour colour = Colour.valueOf(id);

if (colour != null)
colours.put(colour, TCSUtils.getColourFromHex(value));
{
Color colourObj = TCSUtils.getColourFromHex(value);

if (!colourObj.equals(colours.get(colour)))
{
colours.put(colour, colourObj);
isDefaultColour.add(colour);
}
}
}


Expand Down Expand Up @@ -170,7 +186,11 @@ private void loadSetting(String id, String value)
return;
}

settings.put(setting, number);
if (!MathUtils.isEqual(number.floatValue(), settings.get(setting).floatValue()))
{
settings.put(setting, number);
isDefaultSetting.add(setting);
}
}


Expand Down Expand Up @@ -218,4 +238,26 @@ public Number get(Setting key)
{
return settings.get(key);
}


public Map<Colour, Color> getChangedColours()
{
Map<Colour, Color> result = new EnumMap<>(Colour.class);

for (Colour colour : isDefaultColour)
result.put(colour, colours.get(colour));

return result;
}


public Map<Setting, Number> getChangedSettings()
{
Map<Setting, Number> result = new EnumMap<>(Setting.class);

for (Setting setting : isDefaultSetting)
result.put(setting, settings.get(setting));

return result;
}
}
27 changes: 27 additions & 0 deletions core/src/komposten/tcs/util/TCSUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.math.Vector3;

import komposten.utilities.tools.MathOps;


public class TCSUtils
{
Expand Down Expand Up @@ -54,6 +56,31 @@ public static Vector3 createVectorFromAngles(float theta, float phi, float magni
coords.setLength(magnitude);
return coords;
}


/**
* Calculates the colour metrics (theta, phi and r) for a given set of
* Cartesian coordinates.
*
* @return A vector containing theta, phi and r (absolute magnitude) as x, y,
* and z, respectively.
*/
public static Vector3 getMetricsForCoordinates(Vector3 coordinates)
{
float r = coordinates.len();
float theta = -MathOps.angle(0, 0, coordinates.x, coordinates.z);

coordinates.rotateRad(Vector3.Y, -theta);
float phi = MathOps.angle(0, 0, coordinates.x, coordinates.y);

return new Vector3(theta, phi, r);
}


public static Vector3 getMetricsForCoordinates(float x, float y, float z)
{
return getMetricsForCoordinates(new Vector3(x, y, z));
}


public static Color getColourFromHex(String hexColour)
Expand Down

0 comments on commit f17c00c

Please sign in to comment.