Reporting Trend Line - reporting

How would you create a line in JasperReports that follows the trend for the data, in addition to showing the data points? Here are before and after shots:
Before
After
The Time Series report does not appear to have any such option to draw the orange line. (The orange line should be smooth, and thinner, but that's the general idea.)
Any ideas how to craft such a report with iReport 3.7.1?

One solution requires the following items:
BezierLineCustomizer to make the lines curved.
RunningAverageIncrementer to calculate a running average based on a variable.
iReport variable that uses the RunningAverageIncremeter.
BezierLineCustomizer Class
public class BezierLineCustomizer
implements JRChartCustomizer {
public BezierLineCustomizer() {
}
public void customize( JFreeChart jFreeChart, JRChart jrChart ) {
XYPlot xyPlot = ( XYPlot )jFreeChart.getPlot();
XYSplineRenderer splineRenderer = new XYSplineRenderer();
// Make the spline line thick and orange.
//
splineRenderer.setSeriesShapesVisible( 0, false );
splineRenderer.setSeriesShapesVisible( 1, false );
splineRenderer.setSeriesLinesVisible( 1, false );
splineRenderer.setSeriesStroke(
0, new BasicStroke(
4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, null, 0.0f
)
);
splineRenderer.setSeriesPaint( 0, new Color( 255, 140, 0 ) );
splineRenderer.setSeriesVisibleInLegend( 1, Boolean.FALSE );
// Duplicate the data into a new dataset to control its line independently.
//
xyPlot.setDataset( 1, xyPlot.getDataset(0) );
XYItemRenderer defaultRenderer = new XYLineAndShapeRenderer();
defaultRenderer.setSeriesVisible( 0, Boolean.FALSE );
defaultRenderer.setSeriesVisibleInLegend( 0, Boolean.FALSE );
xyPlot.setRenderer( 1, defaultRenderer );
xyPlot.setRenderer( 0, splineRenderer );
}
}
RunningAverageIncrementer Class
public class RunningAverageIncrementer
implements JRIncrementer {
/** Default number of tallies. */
private static final int DEFAULT_TALLIES = 128;
/** Number of tallies within the sliding window. */
private static final int DEFAULT_SLIDING_WINDOW_SIZE = 30;
/** Stores a sliding window of values. */
private List<Double> values = new ArrayList<Double>( DEFAULT_TALLIES );
/**
* Instantiated by the RunningAverageIncrementerFactory class.
*/
public RunningAverageIncrementer() {
}
/**
* Calculates the average of previously known values.
* #return The average of the list of values returned by getValues().
*/
private double calculateAverage() {
double result = 0.0;
List<Double> values = getValues();
for( Double d: getValues() ) {
result += d.doubleValue();
}
return result / values.size();
}
/**
* Called each time a new value to be averaged is received.
* #param value The new value to include for the average.
*/
private void recordValue( Double value ) {
List<Double> values = getValues();
// Throw out
//
if( values.size() > getSlidingWindowSize() ) {
values.remove( 0 );
}
this.values.add( value );
}
private List<Double> getValues() {
return values;
}
private int getIterations() {
return getValues().size();
}
/**
* Returns the newly incremented value, which is calculated by averaging
* the previous value from the previous call to this method.
*
* #param jrFillVariable Unused.
* #param tally New data point to average.
* #param abstractValueProvider Unused.
* #return The newly incremented value.
*/
public Object increment( JRFillVariable jrFillVariable, Object tally,
AbstractValueProvider abstractValueProvider ) {
double value = ((Number)tally).doubleValue();
recordValue( value );
double previousAverage = calculateAverage();
double newAverage =
( ( value - previousAverage ) / ( getIterations() + 1 ) ) + previousAverage;
return new BigDecimal( newAverage );
}
protected int getSlidingWindowSize() {
return DEFAULT_SLIDING_WINDOW_SIZE;
}
}
iReport Variable
Create a variable that uses the RunningAverageIncrementerFactory class (exercise left to the reader). Set its variable expression to the plotted value. Set its initial value expression to zero.
Spline
Set the Customizer Class property of the TimeSeries chart to use the BezierLineCustomizer class.
Result
After these modifications, the running average is clearly visible:

Related

Is there a list of documentation for the properties on the objects used in auto completion?

I'm working on setting up an auto completion list and I've been trying to figure out what each property does. Is there more documentation on this object?
Here's what I have so gathered far:
public class AutoCompleteObject {
public function AutoCompleteObject(name:String = null, metadata:String = null) {
this.value = name;
meta = metadata;
}
/**
* Value written upon auto completion
*
* #see #caption
* */
public var value:String;
/**
* The caption is what is shown in the auto completion list as you type the value
*
* #see #value
* */
public var caption:String;
/**
* The score is a reason unknown
* */
public var score:String;
/**
* What is shown to the right of the value or caption if set in the auto complete list
*
* */
public var meta:String;
/**
* Unknown
* */
public var className:String;
/**
* Unknown
* */
public var matchMask:Object;
/**
* Unknown
* */
public var exactMatch:Object;
/**
* Unknown
* Option: "rightAlignedText"
* */
public var type:String;
}
Here's my function for getting autocompletion objects:
public function getObjectsFromArray(values:Array, metadataType:String = "attribute", className:String = null):Array {
var newValues:Array = [];
var numberOfItems:int = values ? values.length :0;
var autoCompleteObject:AutoCompleteObject;
var testing:Boolean;
var object:Object;
for (var i:int = 0; i < numberOfItems; i++) {
if (testing) {
object = {"value":values[i], meta:metadataType};
newValues.push(object);
}
else {
autoCompleteObject = new AutoCompleteObject(values[i], metadataType);
autoCompleteObject.className = className;
autoCompleteObject.type = "attribute";
newValues.push(autoCompleteObject);
}
}
return newValues;
}
My question is what do the following properties mean:
score (I'm guessing it's a weighted value)
className
type
Less important:
matchMask
exactMatch
My related questions, if they should be separate questions let me know, are:
- if class name is what I think it is can I show className in the autocomplete list?
- can I sort the list by meta type? so my list is above the built in list?
- Should the strongly typed object I'm using be changed to dynamic type for future proofing? I found the other properties mentioned because errors were thrown when I changed from using Object.
I can post these as separate questions.
score is a number used for sorting https://github.com/ajaxorg/ace/blob/v1.2.6/lib/ace/autocomplete.js#L494
matchMask and exactMatch are internal properties used by the sorting algorithm
className is added to the row as a class name https://github.com/ajaxorg/ace/blob/v1.2.6/lib/ace/autocomplete/popup.js#L190
type is a custom property used only by snippet completer https://github.com/ajaxorg/ace/blob/v1.2.6/lib/ace/ext/language_tools.js#L67

Binding Scene size properties to Stage JavaFX

I need to adjust the size of a Scene to the current size of the Stage/Window.
Currently when I resize the Stage/Window the Scene resizes as well, but not to the same size. The Scene contains a StackPane.
I looked for a way to bind but didn't find anything, setters for the size parameters of the Scene also aren't available it seems. Does anyone know a way to get this done?
EDIT: Here's the Code of my Class atm.
public class SimpleSun extends Application {
// Controls
Label lblPos = new Label();
Stage primaryStage;
List<Visibility> vislist;
Scene scene;
Rectangle rect;
Circle circle;
Line line1;
Line line2;
// Variables
private double sunDiameter = 700;
private Integer center = 400;
int fovrad = 80;
int fovpxl = calculatePixelsFromRad(fovrad);
/**
* #param args
* the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
#SuppressWarnings("static-access")
#Override
public void start(final Stage stage) {
// Initialize Containers
this.primaryStage = stage;
primaryStage.setTitle("0.1-alpha -- Sun Simulation");
BorderPane root = new BorderPane();
scene = new Scene(root, 800, 800);
StackPane sp = new StackPane();
// Paint Graphics
rect = new Rectangle(center - fovpxl / 2, center - fovpxl / 2, fovpxl,
fovpxl);
circle = new Circle(400, 400, 350);
line1 = new Line(0, 0, 0, scene.getHeight());
line2 = new Line(0, 0, scene.getHeight(), 0);
// Insert Controls
sp.getChildren().addAll(circle, line1, line2, lblPos, rect);
sp.setAlignment(lblPos, Pos.TOP_LEFT);
lblPos.setStyle("margin-top:10px");
root.setCenter(sp);
primaryStage.setScene(scene);
// Binding Circle size to stage & Scene size to Stage
circle.radiusProperty().bind(
primaryStage.widthProperty().divide(2).subtract(50));
circle.centerXProperty().bind(primaryStage.widthProperty().divide(2));
circle.centerYProperty().bind(primaryStage.widthProperty().divide(2));
// Assign Handlers
line1.setOnMouseClicked(mouseHandler);
line1.setOnMouseMoved(mouseHandler);
line2.setOnMouseClicked(mouseHandler);
line2.setOnMouseMoved(mouseHandler);
circle.setOnMouseClicked(mouseHandler);
circle.setOnMouseMoved(mouseHandler);
rect.setOnMouseClicked(mouseHandler);
rect.setOnMouseMoved(mouseHandler);
scene.widthProperty().addListener(cListener);
scene.heightProperty().addListener(cListener);
// Properties
circle.setFill(Color.YELLOW);
circle.setStroke(Color.BLACK);
rect.setFill(null);
rect.setStroke(Color.BLACK);
primaryStage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_CLICKED) {
int x = (int) mouseEvent.getSceneX();
int y = (int) mouseEvent.getSceneY();
DoubleMatrix1D pCoords = calculateXYRad(x, y);
final ISource p = new GaussianRadialSource(pCoords.get(0),
pCoords.get(1), 1, 1, 0);
MainSimulation.runSim(p, fovrad);
// DEBUG
// String message = "Source Position: " + mouseEvent.getSceneX()
// + " / " + mouseEvent.getSceneY();
// System.out.println(message);
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
int x = (int) mouseEvent.getSceneX();
int y = (int) mouseEvent.getSceneY();
if (mouseEvent.getSource().getClass().equals(Circle.class)) {
((Circle) mouseEvent.getSource())
.setCursor(Cursor.CROSSHAIR);
} else if (mouseEvent.getSource().getClass().equals(Line.class)) {
((Line) mouseEvent.getSource()).setCursor(Cursor.CROSSHAIR);
} else if (mouseEvent.getSource().getClass()
.equals(Rectangle.class)) {
((Rectangle) mouseEvent.getSource())
.setCursor(Cursor.CROSSHAIR);
}
DoubleMatrix1D pCoords = calculateXYRad(x, y);
// Adjust label to new cursor position
lblPos.setText((pCoords.get(0) + " :: " + pCoords.get(1)));
// DEBUG
System.out.println("x: " + pCoords.get(0) + ", y: "
+ pCoords.get(1));
}
}
};
ChangeListener<? super Number> cListener = new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> scenewidth,
Number oldValue, Number newValue) {
// System.out.println(primaryStage.getHeight());
// Adjust Size of Window instead of binding
if (primaryStage.getHeight() < primaryStage.getWidth()) {
primaryStage.setWidth(primaryStage.getHeight());
center = (int) (primaryStage.getHeight() / 2);
sunDiameter = primaryStage.getHeight() - 100;
}
if (primaryStage.getWidth() < primaryStage.getHeight()) {
primaryStage.setHeight(primaryStage.getWidth());
center = (int) (primaryStage.getWidth() / 2);
sunDiameter = primaryStage.getWidth() - 100;
}
// Adjust Center and Sun Diameter to new Window Size
repaintSimpleSun();
System.out.println(primaryStage.getWidth() + " " + primaryStage.getHeight());
System.out.println(scene.getWidth() + " " + scene.getHeight());
System.out.println(center + " " + sunDiameter);
}
};
private DoubleMatrix1D calculateXYRad(int x, int y) {
double X = ((x - center) * (Units.SUN_HALF_DIAMETER_RAD * 2.0) / sunDiameter);
double Y = ((y - center) * (Units.SUN_HALF_DIAMETER_RAD * 2.0) / sunDiameter);
return DoubleFactory1D.dense.make(new double[] { X, Y });
}
private int calculatePixelsFromRad(int rad) {
int pixels = (int) ((sunDiameter) / (Units.SUN_HALF_DIAMETER_RAD * 2) * rad);
// System.out.println(pixels);
return pixels;
}
private void repaintSimpleSun() {
fovpxl = calculatePixelsFromRad(fovrad);
rect.setHeight(fovpxl);
rect.setWidth(fovpxl);
rect.setX(center - (fovpxl / 2));
rect.setY(center - (fovpxl / 2));
line1.setEndY(primaryStage.getWidth());
line2.setEndX(primaryStage.getHeight());
}
}

AS3 random algorithm

I need a suggestion. I want to have a function that returns random numbers from let say 1 to 100, with condition to not repeat the chosen number. It is something like chess table that will be filled with something random and not one thing over another thing... If someone can tell a suggestion I'll be very happy. Thanks.
Create an Array of 100 numbers (1..100), then 'sort' the Array by 'random'. You can then pull out the numbers one at a time working your way through the array.
I haven't tested the code below but I had these snippets available that you could piece together to achieve the intended result.
public static function randomNumber(min:Number, max:Number):Number{
var rnd:Number = Math.floor((Math.random()*((max+1)-min))+min);
return rnd;
}
public static function randomize(arr:Array):Array{
var len:Number = arr.length;
var rnd:Number;
var tmp:Object;
for(var i:Number=0;i<len;i++){
rnd = randomNumber(0,(len-1));
tmp = arr[i];
arr[i] = arr[rnd];
arr[rnd] = tmp;
}
return arr;
}
var setOfNumbers:Array = new Array();
for(var i:int=0;i<100;i++){
setOfNumbers[i] = (i+1);
}
var shuffledSetOfNumbers:Array = randomize(setOfNumbers);
Notes:
For the purists this "randomizing" isn't "truly" random (if you're writing a Card shuffler for a Vegas gambling machine you'll want to use something different - case in point!)
My randomNumber and randomize functions above are static as I've typically included them that way in the apps I've needed them but you don't have to use it this way
My original lib used Number vs int or uint for some of the variables for more options when used but feel free to clean that up
also like that...
package
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* #author Vadym Gordiienko
*/
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var startArray:Array = generateNumberArray(100);
var randomArray:Array = randomArray(startArray);
trace("startArray = " + startArray);
trace("randomArray = " + randomArray);
}
/**
* generate Array of numbers by length
* #param length
* #return Array of numbers
*/
public static function generateNumberArray(length:int):Array
{
var numberArray:Array = [];
for (var i:int = 0; i < length; i++)
{
numberArray[i] = i+1;
}
return numberArray;
}
/**
* generate randomly mixed array by input array
* #param inputArray - simple not mixed array
* #return Array - mixed array
*/
public static function randomArray(inputArray:Array):Array
{
var randomArray:Array = [];
var tempArray:Array = [];
for (var i:int = 0; i < inputArray.length; i++)
{
tempArray.push(inputArray[i]);
}
while (tempArray.length)
{
var randomNumber:int = Math.round(Math.random() * (tempArray.length - 1));// get random number of left array
randomArray.push( tempArray[randomNumber] );
tempArray.splice(randomNumber, 1); // remove randomed element from temporary aarray
}
tempArray = null;
delete [tempArray];
return randomArray;
}
}
}

Count the number of points closer than a given distance

I'm developing a project that given a set of coordinates (lat and longitude) needs to find all the points that are closer than a given distance (in Km).
I have working implementation that iterates over each point and for each point iterates over all the other points. This is O(n^2). I'd like to know what approach could I follow to improve this, having in mind that I don't want the closest point but the ones that are closer than x Km (also I'd like to be able to do the opposite, finding all the points that are further away than x Km).
If you could provide some ideas and algorithms it would be nice. Also code examples would be nice, specially in Scala (I'm developing this project Scala).
For this problem I'd use a java library (this is possible in Scala).
Calculating distances on earth is much more difficult than you think. The earth is not a pefect sphere for example.
The main library for doing 'geo stuff' in java is JTS: http://tsusiatsoftware.net/jts/main.html
You can also take a look at Geotools or maybe even a GIS-database like PostGIS (built on Postgresql), but that might be overkill for your project
Answering myself a few months late. Well I ended up using using KD-Tree to implement this. I based myself on this Java implementation: http://people.cs.vt.edu/~shaffer/Book/JAVA/progs/KDtree/
However I made some modifications to it (including porting it to Scala) and adapting it to my specific problem around Geocaches. The resulting code was the following:
/*
* Based on
* http://people.cs.vt.edu/~shaffer/Book/JAVA/progs/KDtree/
*
* That code is made available as part of this textbook on Data Structures:
* http://people.cs.vt.edu/~shaffer/Book/
*/
//A node for a KDTree
class KDNode[E] {
private var key_value : Array[Double] = null //key for this node
def key = key_value
def key_=(k : Array[Double]) { key_value = k }
private var element_value: E = _ //Element for this node
def element = element_value
def element_=(e : E) {element_value = e}
private var left_value : KDNode[E] = null //Pointer to left child
def left = left_value
def left_=(l : KDNode[E]) {left_value = l}
private var right_value : KDNode[E] = null //Pointer to right child
def right = right_value
def right_=(r : KDNode[E]) {right_value = r}
/** Constructors */
def this(k : Array[Double], value : E) =
{
this()
key = k
element = value
}
def this(k : Array[Double], value : E, l : KDNode[E], r : KDNode[E]) =
{
this(k,value)
left = l
right = r
}
//Checks if it's a leaf
def isLeaf : Boolean =
{
return (left == null) && (right == null)
}
}
//Trait for a basic Dictionary that will be used as basis for our KDTree
trait Dictionary[K,V] {
def size: Int
def insert(key: K, value: V)
def remove(key: K): V
def find(key: K): V
def clear
def isEmpty: Boolean
}
/**
* A extended trait that defines that the key of the dictionary is an array of
* doubles and defines the need of a method called regionSearchGeo (very
* important for All Years 5 & 6 stats)
*/
trait GeoDictionary[E] extends Dictionary[Array[Double], E] {
def regionSearchGeo(k: Array[Double], radius: Double) : List[E]
}
/**
* Our implementation of a KDTree. It's based on the code provided in the
* reference above, but had a few key areas modified for geographic searching.
* For example, this KDtree is a 3D Tree. The keys are Latitude, Longitude and
* the Year of the cache (that was also included to speed thins even further)
*/
class K3DGeoTree[E] extends GeoDictionary[E]{
private var root : KDNode[E] = null
private val D : Int = 3 // Only supporting 2D points in this implementation
private var nodecount : Int = 0 // Number of nodes in the KD tree
/**
* Implementing everything that is required by the Dictionary trait
* Some private auxiliary methods are also present
*/
def clear() = { root = null }
def isEmpty() : Boolean = { root == null }
def size() : Int = { return nodecount }
def insert(pt : Array[Double], value : E) = {
root = inserthelp(root, pt, value, 0)
nodecount=nodecount+1
}
def inserthelp(rt : KDNode[E], key : Array[Double], value : E, level : Int)
: KDNode[E] = {
if (rt == null) return new KDNode[E](key, value)
val rtkey : Array[Double] = rt.key
if (rtkey(level) > key(level))
rt.left = inserthelp(rt.left, key, value, (level+1)%D)
else
rt.right = inserthelp(rt.right, key, value, (level+1)%D)
return rt
}
private def findmin(rt : KDNode[E], descrim : Int, level : Int): KDNode[E]= {
var temp1 : KDNode[E] = null
var temp2 : KDNode[E] = null
var key1 : Array[Double] = null
var key2 : Array[Double] = null
if (rt == null) return null
temp1 = findmin(rt.left, descrim, (level+1)%D)
if (temp1 != null) key1 = temp1.key
if (descrim != level) {
temp2 = findmin(rt.right, descrim, (level+1)%D)
if (temp2 != null) key2 = temp2.key
if ((temp1 == null) || ((temp2 != null) && (key1(descrim) > key2(descrim))))
temp1 = temp2
key1 = key2
} // Now, temp1 has the smaller value
var rtkey : Array[Double] = rt.key
if ((temp1 == null) || (key1(descrim) > rtkey(descrim)))
return rt
else
return temp1
}
def find(key : Array[Double]) : E = { return findhelp(root, key, 0) }
private def findhelp(rt : KDNode[E], key : Array[Double], level : Int) : E ={
if (rt == null) return null.asInstanceOf[E]
val it : E = rt.element
val itkey : Array[Double]= rt.key
if ((itkey(0) == key(0)) && (itkey(1) == key(1)))
return rt.element
if (itkey(level) > key(level))
return findhelp(rt.left, key, (level+1)%D)
else
return findhelp(rt.right, key, (level+1)%D)
}
def remove(key : Array[Double]) : E = {
val temp : E = findhelp(root, key, 0) // First find it
if (temp != null) {
root = removehelp(root, key, 0) // Now remove it
nodecount=nodecount-1
}
return temp
}
private def removehelp(rt : KDNode[E], key : Array[Double], level : Int)
: KDNode[E] = {
if (rt == null) return null
val rtkey : Array[Double] = rt.key
if (key(level) < rtkey(level))
rt.left = removehelp(rt.left, key, (level+1)%D)
else if (key(level) > rtkey(level))
rt.right = removehelp(rt.right, key, (level+1)%D)
else { // Found it
if (rt.right == null)
if (rt.left == null) // Just drop element
return null
else { // Switch subtree to right
rt.right = rt.left
rt.left = null
}
val temp : KDNode[E] = findmin(rt.right, level, (level+1)%D)
rt.right = removehelp(rt.right, temp.key, (level+1)%D)
rt.element = temp.element
}
return rt
}
/**
* Implementing the GeoDictionary trait
*/
def regionSearchGeo(point: Array[Double], radius: Double) : List[E] =
{
val pointGeo : GeoLocation = GeoLocation.fromDegrees(point(0), point(1))
/**
* Calculates a bounding rectangle that contains the circle with the given
* radius. This will be explained later in the corresponding class
*/
val boundingRect = pointGeo.boundingCoordinates(radius)
//Return the caches found
return rsGeoHelp(root, point, radius, boundingRect, 0)
}
/**
* Auxiliary region search function that does all the heavy work
*/
private def rsGeoHelp(rt : KDNode[E], point : Array[Double], radius : Double,
boundingRect : Tuple2[GeoLocation,GeoLocation],
lev : Int): List[E] = {
if (rt == null) return Nil
val rtkey : Array[Double] = rt.key
var found : List[E] = Nil
//Checks if the current node is in the desired radius (and also the year)
if (InCircleGeo(point, radius, rtkey))
found = List(rt.element)
//First Dimension is latitude
if(lev % D == 0){
if (rtkey(lev) >= boundingRect._1.degLat)
found = found:::rsGeoHelp(rt.left, point, radius, boundingRect, (lev+1)%D)
if (rtkey(lev) <= boundingRect._2.degLat)
found = found:::rsGeoHelp(rt.right, point, radius, boundingRect, (lev+1)%D)
}
//Second Dimension is Longitude
else if(lev % D == 1){
if (rtkey(lev) >= boundingRect._1.degLon)
found = found:::rsGeoHelp(rt.left, point, radius, boundingRect, (lev+1)%D)
if (rtkey(lev) <= boundingRect._2.degLon)
found = found:::rsGeoHelp(rt.right, point, radius, boundingRect, (lev+1)%D)
}
//Third and last dimension is the year
else{
found = found:::rsGeoHelp(rt.left, point, radius, boundingRect, (lev+1)%D)
if (rtkey(lev) <= point(lev))
found = found:::rsGeoHelp(rt.right, point, radius, boundingRect, (lev+1)%D)
}
//Return the found nodes (in our case it will be caches)
return found
}
private def InCircleGeo(point : Array[Double], radius : Double,
coord : Array[Double]) : Boolean = {
//Creates a GeoLocation object for each point
val pointGeo : GeoLocation = GeoLocation.fromDegrees(point(0), point(1))
val coordGeo : GeoLocation = GeoLocation.fromDegrees(coord(0), coord(1))
/**
* If the year is smaller than the query point and the distance is within
* radius return true. Else it's false.
*/
return (coord(0) != point(0) && coord(1) != point(1) && coord(2) <= point(2)
&& pointGeo.distanceTo(coordGeo) < radius)
}
}
/**
* This class encapsulates a series of utility methods to deal with geographic
* coordinates. It was based on the information in the link below that gives
* a very good insight about how to do math with geographic coordinates and
* also provides some Java samples that we used as an inspiration for this
* class.
* Link: http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
*/
//Companion object of Class GeoLocation to define static methods and variables
object GeoLocation {
//Min maxs in terms of Latitude and Longitude accross the globe
private val MIN_LAT : Double = math.toRadians(-90) // -PI/2
private val MAX_LAT : Double = math.toRadians(90) // PI/2
private val MIN_LON : Double = math.toRadians(-180) // -PI
private val MAX_LON : Double = math.toRadians(180) // PI
/**
* Earth radius. This value is the most used but there are others that may
* give slightly different results.
*/
private val RADIUS : Double = 6372.8
/**
* A factory method that creates a GeoLocation object from given latitude and
* longitude in degrees
*/
def fromDegrees(latitude : Double, longitude : Double) : GeoLocation = {
val result : GeoLocation = new GeoLocation()
result.radLat = math.toRadians(latitude)
result.radLon = math.toRadians(longitude)
result.degLat = latitude
result.degLon = longitude
result.checkBounds
return result
}
/**
* A factory method that creates a GeoLocation object from given latitude and
* longitude in radians
*/
def fromRadians(latitude : Double, longitude : Double) : GeoLocation = {
val result : GeoLocation = new GeoLocation()
result.radLat = latitude
result.radLon = longitude
result.degLat = math.toDegrees(latitude)
result.degLon = math.toDegrees(longitude)
result.checkBounds
return result
}
}
/**
* The GeoLocation class itself. The constructor is private use the factory
* methods above.
*/
class GeoLocation private{
/**
* Getters and Setters implemented as properties with syntactic sugar
* This properties contain the latitude and longitude in degrees and radians
*/
private var radLat_value : Double = _
def radLat = radLat_value
private def radLat_=(k : Double) { radLat_value = k }
private var radLon_value : Double = _
def radLon = radLon_value
private def radLon_=(k : Double) { radLon_value = k }
private var degLat_value : Double = _
def degLat = degLat_value
private def degLat_=(k : Double) { degLat_value = k }
private var degLon_value : Double = _
def degLon = degLon_value
private def degLon_=(k : Double) { degLon_value = k }
/**
* Check if the vales are valid considering the MIN and MAX for latitude and
* longitude.
*/
private def checkBounds = {
if (radLat < GeoLocation.MIN_LAT || radLat > GeoLocation.MAX_LAT ||
radLon < GeoLocation.MIN_LON || radLon > GeoLocation.MAX_LON)
throw new IllegalArgumentException()
}
/**
* Function to calculate the distance between this GeoLocation and the given
* GeoLocation.
*
* Check the reference above and
* http://en.wikipedia.org/wiki/Haversine_formula
* for more information.
*/
def distanceTo(location : GeoLocation) : Double = {
return math.acos(math.sin(radLat) * math.sin(location.radLat) +
math.cos(radLat) * math.cos(location.radLat) *
math.cos(radLon - location.radLon)) * GeoLocation.RADIUS
}
/**
* This method is very important for the search made in the K3DTree.
* It allows us to make a bouding rectangle with the given distance/radius
* that is geometrically correct. Check the reference above to learn more
* about the math involved.
*/
def boundingCoordinates(distance : Double)
: Tuple2[GeoLocation, GeoLocation] = {
if (distance < 0d) throw new IllegalArgumentException()
// Angular distance in radians on a great circle
val radDist : Double = distance / GeoLocation.RADIUS
//Initialize local variables to check for poles
var minLat : Double = radLat - radDist
var maxLat : Double = radLat + radDist
var minLon : Double = 0
var maxLon : Double = 0
//Normal case
if (minLat > GeoLocation.MIN_LAT && maxLat < GeoLocation.MAX_LAT) {
val deltaLon : Double = math.asin(math.sin(radDist) / math.cos(radLat))
minLon = radLon - deltaLon
if (minLon < GeoLocation.MIN_LON) minLon += 2d * math.Pi
maxLon = radLon + deltaLon
if (maxLon > GeoLocation.MAX_LON) maxLon -= 2d * math.Pi
}
//Special case in which a pole is within the distance
else{
minLat = math.max(minLat, GeoLocation.MIN_LAT)
maxLat = math.min(maxLat, GeoLocation.MAX_LAT)
minLon = GeoLocation.MIN_LON
maxLon = GeoLocation.MAX_LON
}
/**
* Each of the bounding points (one in the south-west, bottom-left,
* and other in the north-east, top-right)
*/
val swPoint : GeoLocation = GeoLocation.fromRadians(minLat, minLon)
val nePoint : GeoLocation = GeoLocation.fromRadians(maxLat, maxLon)
//Return the tuple with the two points
return (swPoint, nePoint)
}
}
The whole code is documented so I hope this helps someone with a similar problem. In this specific problem I had to deal with years besides latitude and longitude, so I added an extra dimension. But for a more general geographic problem it's even easier to do it with only two dimensions (one for latitude and one for longitude).

Texturing a terrain causes Windows Phone to crash (without an exception) or Models are not drawn afterwards

I call this method on LoadContent() - after loading heightMap texture:
private void setEffect(Texture2D heightMap)
{
m_BasicEffect = new BasicEffect(this.GraphicsDevice);
m_BasicEffect.EnableDefaultLighting();
m_BasicEffect.FogEnabled = true;
m_BasicEffect.FogStart = 300f;
m_BasicEffect.FogEnd = 1000f;
m_BasicEffect.FogColor = Color.Black.ToVector3();
m_BasicEffect.TextureEnabled = true;
m_BasicEffect.World = Matrix.Identity;
m_BasicEffect.Texture = heightMap;
}
Now, if I change the "m_BasicEffect.TextureEnabled = true;" to "m_BasicEffect.TextureEnabled = false;" it works, but the texture (of course) doesn't show.
Draw method looks like this:
public override void Draw(Microsoft.Xna.Framework.GameTime i_GameTime)
{
Matrix worldMatrix = Matrix.CreateTranslation(-m_TerrainWidth / 2.0f, 0, m_TerrainHeight / 2.0f) * Matrix.CreateRotationY(m_Angle);
m_BasicEffect.View = MyCamera.View;
m_BasicEffect.Projection = MyCamera.Projection;
m_BasicEffect.World = worldMatrix;
foreach (EffectPass pass in m_BasicEffect.CurrentTechnique.Passes)
{
pass.Apply();
Game.GraphicsDevice.Indices = myIndexBuffer;
Game.GraphicsDevice.SetVertexBuffer(myVertexBuffer);
Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, m_VerticesNormalLength, 0, m_IndicesLength / 3);
}
}
Moreover, if I try to draw Models afterwords, it throws an exception:
"The current vertex declaration does not include all the elements required by the current vertex shader."
The way I try to draw the Models:
public override void Draw(GameTime i_GameTime)
{
Matrix[] transforms = new Matrix[MyModel.Bones.Count];
MyModel.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in MyModel.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.Projection = MyCamera.Projection;
be.View = MyCamera.View;
be.World = GetWorld() * mesh.ParentBone.Transform;
}
mesh.Draw();
}
}
What do you think about it?
Thanks in advance.

Resources