this is my complete code for a small gui to take variables from user and return them to the rest of program(r.o.p) for calculations, however doesn't seem to be passing to r.o.p. and no output file is observerd.
Any help would be much appreciated, I think the problem is with the listener for the Draw New Graph command. Thanks
Code:
import java.text.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class RungeKutta {
// class to create slider and window
private static File file1;
public static double A(double v, double x, double wc, double beta) {
return (-2 * beta * v - (Math.pow(wc, 2)) * Math.sin(x));
}
public static File getFile1() {
return file1;
}
public static void setFile1(File file1) {
RungeKutta.file1 = file1;
}
public static void main(String[] argv) throws IOException, ParseException {
createAndShowGUI();
}
private static void createAndShowGUI() {
//create and set up the window.
JFrame frame = new JFrame("RungeKutta");
GridLayout first = new GridLayout(14,1);
frame.setLayout(first);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create, name and Populate TextField
JTextField PL = new JTextField("Pendulum Length", 20);
//Set TextField to Uneditable. Each will have Empty Field Below For Variables
PL.setEditable(false);
//Set Textfield for user entered dat
JTextField PLv = new JTextField();
//Allow input from text field to be taken
JTextField AD = new JTextField("Angular Displacement", 20);
AD.setEditable(false);
JTextField ADv = new JTextField();
JTextField AV = new JTextField("Angular Velocity", 20);
AV.setEditable(false);
JTextField Avv = new JTextField();
JTextField TS= new JTextField("Time Steps", 20);
TS.setEditable(false);
JTextField TSv = new JTextField();
JTextField MT = new JTextField("Max Time", 20);
MT.setEditable(false);
JTextField MTv = new JTextField();
JTextField V = new JTextField("Viscosity (0-1)", 20);
V.setEditable(false);
JTextField Vv = new JTextField();
//Create Button to Restart and Button to take in Values for usage
JLabel emptyLabel = new JLabel("");
emptyLabel.setPreferredSize(new Dimension(600,500));
frame.getContentPane().add(PL, first);
frame.getContentPane().add(PLv, first);
frame.getContentPane().add(AD, first);
frame.getContentPane().add(ADv, first);
frame.getContentPane().add(AV, first);
frame.getContentPane().add(Avv, first);
frame.getContentPane().add(TS, first);
frame.getContentPane().add(TSv, first);
frame.getContentPane().add(MT, first);
frame.getContentPane().add(MTv, first);
frame.getContentPane().add(V, first);
frame.getContentPane().add(Vv, first);
JButton BNewGraph = new JButton("Draw New Graph"); //Button to restart entire drawing process
frame.getContentPane().add(BNewGraph, first);
//display the window
frame.pack();
frame.setVisible(true);
class intakegui implements ActionListener
{
public intakegui()
{
BNewGraph.addActionListener((ActionListener) this);
BNewGraph.setActionCommand("Click to Draw");
}
#Override
public void actionPerformed(ActionEvent e) {
double l = Double.parseDouble(PLv.getText());
double xi = Double.parseDouble(ADv.getText());
double vi = Double.parseDouble(Avv.getText());
double dt = Double.parseDouble(TSv.getText());
double n = Double.parseDouble(MTv.getText());
double beta = Double.parseDouble(Vv.getText());
SimpleDateFormat dform = new SimpleDateFormat("ddMMyyyysmH");
Date d = Calendar.getInstance().getTime();
String dstr = dform.format(d);
String filename = ("result " + dstr + ".txt");
file1 = new File(filename);
PrintWriter savedValues = null;
try {
savedValues = new PrintWriter(filename);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//declare variable for gravity and omega*c
double g = 9.8;
double wc = Math.sqrt(g / l);
savedValues.println("#Initial Values Entered");
savedValues.println("#" + l + "," + vi + "," + xi + "," + dt + "," + n
+ "," + beta);
double[] dispTime = new double[(int) n];
double[] velTime = new double[(int) n];
// let a = angular acceleration
for (double j = 0; j < (int) n; j++) {
// int time = 1;
double k1v = dt * j * A(vi, xi, wc, beta);
double k1x = dt * j * vi;
double k2v = dt * j * A(vi, xi + (0.5 * k1x), wc, beta);
double k2x = dt * j * (vi + (0.5 * k1v));
double k3v = dt * j * A(vi, xi + (0.5 * k2x), wc, beta);
double k3x = dt * j * (vi + (0.5 * k2v));
double k4v = dt * j * A(vi, xi + k3x, wc, beta);
double k4x = dt * j * (vi + k3v);
xi += k1x / 6 + k2x / 3 + k3x / 3 + k4x / 6;
vi += k1v / 6 + k2v / 3 + k3v / 3 + k4v / 6;
dispTime[(int) j] = xi;
velTime[(int) j] = vi;
System.out.println(xi + "," + vi);
}
for (int i = 0; i < (int) n; i++) {
savedValues.println(dispTime[i] + " " + velTime[i]);
}
savedValues.close();
System.out.println("File saved. File name: " + filename);
}
}
}
}
You forgot to add listener to your button. You need to add listener as below:
BNewGraph.addActionListener(new intakegui());
Now when user clicks on button, you would see the file.
Related
As an exercise I am trying to calculate a recursive EMA with a burn period in Esper, EPL. It has moderately complex startup logic, and I thought this would be a good test for evaluating the sorts of things Esper could achieve.
Assuming a stream of values x1, x2, x3 at regular intervals, we want to calculate:
let p = 0.1
a = average(x1, x2, x3, x4, x5) // Assume 5, in reality use a parameter
y1 = p * x1 + (p - 1) * a // Recursive calculation initialized with look-ahead average
y2 = p * x2 + (p - 1) * y1
y3 = p * x3 + (p - 1) * y2
....
The final stream should only publish y5, y6, y7, ...
I was toying with a context that produces an event containing the average a, and that event triggers a second context that begins the recursive calculations. But by the time I try to get the first context to trigger once and once only, and the second context to handle the initial case using a and subsequent events recursively I end up with a messy tangle of logic.
Is there a straight-forward way to approach this problem?
(I'm ignoring using a custom aggregator, since this is a learning exercise)
This doesn't answer the question, but might be useful - implementation as a custom aggregation function, tested with esper 7.1.0
public class EmaFactory implements AggregationFunctionFactory {
int burn = 0;
#Override
public void setFunctionName(String s) {
// Don't know why/when this is called
}
#Override
public void validate(AggregationValidationContext ctx) {
#SuppressWarnings("rawtypes")
Class[] p = ctx.getParameterTypes();
if ((p.length != 3)) {
throw new IllegalArgumentException(String.format(
"Ema aggregation required three parameters, received %d",
p.length));
}
if (
!(
(p[0] == Double.class || p[0] == double.class) ||
(p[1] == Double.class || p[1] == double.class) ||
(p[2] == Integer.class || p[2] == int.class))) {
throw new IllegalArgumentException(
String.format(
"Arguments to Ema aggregation must of types (Double, Double, Integer), got (%s, %s, %s)\n",
p[0].getName(), p[1].getName(), p[2].getName()) +
"This should be made nicer, see AggregationMethodFactorySum.java in the Esper source code for " +
"examples of correctly dealing with multiple types"
);
}
if (!ctx.getIsConstantValue()[2]) {
throw new IllegalArgumentException(
"Third argument 'burn' to Ema aggregation must be constant"
);
}
;
burn = (int) ctx.getConstantValues()[2];
}
#Override
public AggregationMethod newAggregator() {
return new EmaAggregationFunction(burn);
}
#SuppressWarnings("rawtypes")
#Override
public Class getValueType() {
return Double.class;
}
}
public class EmaAggregationFunction implements AggregationMethod {
final private int burnLength;
private double[] burnValues;
private int count = 0;
private double value = 0.;
EmaAggregationFunction(int burn) {
this.burnLength = burn;
this.burnValues = new double[burn];
}
private void update(double x, double alpha) {
if (count < burnLength) {
value += x;
burnValues[count++] = x;
if (count == burnLength) {
value /= count;
for (double v : burnValues) {
value = alpha * v + (1 - alpha) * value;
}
// in case burn is long, free memory
burnValues = null;
}
} else {
value = alpha * x + (1 - alpha) * value;
}
}
#Override
public void enter(Object tmp) {
Object[] o = (Object[]) tmp;
assert o[0] != null;
assert o[1] != null;
assert o[2] != null;
assert (int) o[2] == burnLength;
update((double) o[0], (double) o[1]);
}
#Override
public void leave(Object o) {
}
#Override
public Object getValue() {
if (count < burnLength) {
return null;
} else {
return value;
}
}
#Override
public void clear() {
// I don't know when / why this is called - this part untested
count = 0;
value = 0.;
burnValues = new double[burnLength];
}
}
public class TestEmaAggregation {
private EPRuntime epRuntime;
private SupportUpdateListener listener = new SupportUpdateListener();
void send(int id, double value) {
epRuntime.sendEvent(
new HashMap<String, Object>() {{
put("id", id);
put("value", value);
}},
"CalculationEvent");
}
#BeforeEach
public void beforeEach() {
EPServiceProvider provider = EPServiceProviderManager.getDefaultProvider();
EPAdministrator epAdministrator = provider.getEPAdministrator();
epRuntime = provider.getEPRuntime();
ConfigurationOperations config = epAdministrator.getConfiguration();
config.addPlugInAggregationFunctionFactory("ema", EmaFactory.class.getName());
config.addEventType(
"CalculationEvent",
new HashMap<String, Object>() {{ put("id", Integer.class); put("value", Double.class); }}
);
EPStatement stmt = epAdministrator.createEPL("select ema(value, 0.1, 5) as ema from CalculationEvent where value is not null");
stmt.addListener(listener);
}
Double getEma() {
return (Double)listener.assertOneGetNewAndReset().get("ema");
}
#Test
public void someTest() {
send(1, 1);
assertEquals(null, getEma());
send(1, 2);
assertEquals(null, getEma());
send(1, 3);
assertEquals(null, getEma());
send(1, 4);
assertEquals(null, getEma());
// Last of the burn period
// We expect:
// a = (1+2+3+4+5) / 5 = 3
// y1 = 0.1 * 1 + 0.9 * 3 = 2.8
// y2 = 0.1 * 2 + 0.9 * 2.8
// ... leading to
// y5 = 3.08588
send(1, 5);
assertEquals(3.08588, getEma(), 1e-10);
// Outside burn period
send(1, 6);
assertEquals(3.377292, getEma(), 1e-10);
send(1, 7);
assertEquals(3.7395628, getEma(), 1e-10);
send(1, 8);
assertEquals(4.16560652, getEma(), 1e-10);
}
}
I need to call 4 APIs on a same server and then use the result to create a list and want to pass the same list to create a pie chart.
I have created a list but unable to pass that list in pie chart.
main() async {
// returned dataset example:
// [{females: 1367341, country: Brazil, age: 18, males: 1368729,
year: 1980, total: 2736070}]
final age18data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/18/');
final age30data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/30/');
final age45data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/45/');
final age60data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/60/');
final values = [
age18data[0]["total"],
age30data[0]["total"],
age45data[0]["total"],
age60data[0]["total"]
];
I have done till here now I want to use these values list to draw the pie chart using charts_flutter package
Here you go, 4 api calls to same server, and a pie chart:
import "dart:math" as math;
import "dart:io";
import "dart:convert";
main() async {
// returned dataset example:
// [{females: 1367341, country: Brazil, age: 18, males: 1368729, year: 1980, total: 2736070}]
final age18data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/18/');
final age30data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/30/');
final age45data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/45/');
final age60data = await getJson(
'http://api.population.io:80/1.0/population/2019/India/60/');
final values = [
age18data[0]["total"],
age30data[0]["total"],
age45data[0]["total"],
age60data[0]["total"]
];
final allTotal = values[0] + values[1] + values[2] + values[3];
final proportion = values.map((v) => v / allTotal).toList();
print("Population of India:");
print("A - 18 y.o. ${values[0]} (${proportion[0]})");
print("B - 25 y.o. ${values[1]} (${proportion[1]})");
print("C - 45 y.o. ${values[2]} (${proportion[2]})");
print("D - 60 y.o. ${values[3]} (${proportion[3]})");
final labels = ["A", "B", "C", "D"];
asciiPieChart(labels, proportion);
}
Future<dynamic> getJson(String url) async {
var request =
await HttpClient().getUrl(Uri.parse(url)); // produces a request object
var response = await request.close(); // sends the request
var body = await response.transform(Utf8Decoder()).join("");
return json.decode(body);
}
void asciiPieChart(dynamic k, dynamic v) {
// adapted from javascript version:
// https://codegolf.stackexchange.com/a/23351/18464
dynamic d, y, s, x, r, a, i, f, p, t, j;
r = 10.0;
d = r * 2;
p = [];
for (y = 0; y < d; y++) {
p.add([]);
for (x = 0; x < d; x++) p[y].add(" ");
}
t = 0;
i = -1;
for (f = 0; f < 1; f += 1 / (r * 20)) {
if (f > t) t += v[++i];
a = math.pi * 2 * f;
for (j = 0; j < r; j++) {
int px = ((math.sin(a) * j).round() + r).toInt();
int py = ((math.cos(a) * j).round() + r).toInt();
p[px][py] = k[i < 0 ? k.length + i : i];
}
}
s = "";
for (y = 0; y < d; y++) {
for (x = 0; x < d; x++) s += p[y][x];
s += "\n";
}
print(s);
}
Run dart example.dart prints out:
Population of India:
A - 18 y.o. 25026690 (0.33671242865945705)
B - 25 y.o. 22643410 (0.30464746133954734)
C - 45 y.o. 16325200 (0.21964142043359983)
A - 60 y.o. 10331300 (0.13899868956739578)
CCCCCCC
CCCCCCCCCCC
CCCCCCCCCCCCD
BBCCCCCCCCCCDDD
BBBBCCCCCCCCDDDDD
BBBBBCCCCCCDDDDDD
BBBBBBBCCCCCDDDDDDD
BBBBBBBCCCDDDDDDDDD
BBBBBBBBCCDDDDDDDDD
BBBBBBBBBDDDDDDDDDD
BBBBBBBBBAAAAAAAAAA
BBBBBBBBBAAAAAAAAAA
BBBBBBBBAAAAAAAAAAA
BBBBBBAAAAAAAAAAA
BBBBBBAAAAAAAAAAA
BBBBAAAAAAAAAAA
BBBAAAAAAAAAA
BAAAAAAAAAA
AAAAAAA
You can of-course apply same ideas and use different charting method for example as described in
https://google.github.io/charts/flutter/example/pie_charts/donut.html
Doing http requests also is easier with https://pub.dartlang.org/packages/http
I try to make a grid of squares, where I could control every square's color parameters individually ie. make them flash one by one or all at the same time.
I'm trying to do it with tweens, running the parameters with for-loop.
The code below tries to flash all the squares at the same time, once in every second. but for some reason all of the squares don't tween, only some do. Or they tween partly and sometimes they don't tween at all. However, the pattern doesn't repeat itself.
Is this too many tweens at the same time? Is the for-loop right way to do this? Should I use MovieClips instead of Sprites? If I want to control colors in many differeng objects in a very fast phase, what would be the best way to do it?
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
import flash.display.*;
import flash.events.*;
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import Math;
import flash.utils.Timer;
import flash.events.TimerEvent;
import resolumeCom.*;
import resolumeCom.parameters.*;
import resolumeCom.events.*;
public class LightGrid extends MovieClip
{
private var t1:Tween;
private var resolume:Resolume = new Resolume();
private var tempo:FloatParameter = resolume.addFloatParameter("Tempo", 0.6);
private var pad = 3;
private var dim = 20;
private var posX = 0 + pad;
private var posY = 0 + pad;
private var a:Number = new Number();
private var b:Number = new Number();
private var blk:Number = new Number();
var newCol:ColorTransform = new ColorTransform();
public function LightGrid()
{
resolume.addParameterListener(parameterChanged);
for (var b = 0; b < 16; b++)
{
posY = (b*dim) + (b*pad) + pad;
trace("New row");
for (var a = 0; a < 24; a++)
{
posX = (a*dim) + (a*pad) + pad;
// l = line, f = fill
var l:Sprite = new Sprite;
l.graphics.lineStyle(2, 0xFFFFF, 1);
l.graphics.drawRect(posX, posY, dim, dim);
l.name = "line_Row" + b + "Col" + a;
addChild(l);
var f:Sprite = new Sprite;
f.graphics.beginFill(0x990000, 1);
f.graphics.drawRect(posX, posY, dim, dim);
f.graphics.endFill();
f.name = "fill_Row" + b + "Col" + a;
addChild(f);
trace(getChildByName("fill_Row" + b + "Col" + a).name);
}
}
var myTimer:Timer = new Timer(1000, 100);
myTimer.addEventListener("timer", timerHandler);
myTimer.start();
}
public function timerHandler(event:TimerEvent):void {
flashTheLights();
}
public function parameterChanged(e:ChangeEvent):void
{
if (e.object == tempo)
{
}
}
public function flashTheLights():void
{
blk = 0;
for (var blk = 0; blk < (24/3); blk++)
{
for (var d = 0; d < 16; d++)
{
for (var c = (0+(3*blk)); c < (3+(3*blk)); c++)
{
newCol.redOffset=30-(35*blk);
newCol.blueOffset=200+(7*blk);
newCol.greenOffset=200;
trace(getChildByName("fill_Row" + d + "Col" + c).name);
var fill:Sprite = getChildByName("fill_Row" + d + "Col" + c) as Sprite;
fill.transform.colorTransform.alphaMultiplier = -255;
fill.transform.colorTransform = newCol;
trace("Run tween");
var myTween = new Tween(fill,'alpha',Regular.easeIn,1,0,0.3,true);
}
}
trace("Done!" + blk);
}
}
}
I kinda solved the problem by stacking the sprites under movieclips so I only tween couple of elements instead of tens or hundreds
for (var k = 0; k < (grdX/ptrnSz); k++)
{
var ptrn:MovieClip = new MovieClip();
ptrn.name = "ptrn" + k;
addChild(ptrn);
ptrn.alpha = 0.01;
ptrnAm++;
for (var d = 0; d < grdY; d++)
{
posY = (d*dim) + (d*pad) + top;
for (var c = (0+(ptrnSz*k)); c < (ptrnSz+(ptrnSz*k)); c++)
{
posX = (c*dim) + (c*pad) + left;
// l = line, f = fill
var f:Sprite = new Sprite;
f.graphics.beginFill(0xFFFFFF, 1);
f.graphics.drawRect(posX-0.5, posY, dim, dim);
f.graphics.endFill();
f.name = "fill_Block" + k + "Row" + d + "Col" + c;
ptrn.addChild(f);
}
}
}
grdX = Grid size in X-axis (how many columns)
ptrnSz = size of the movieclips containing the Sprites (how many columns)
After that I just tween movieclips with TweenMax, calling them each with getChildByName.
Ive ported over some c code that renders a sphere in opengl for a webgl/typescript project I'm working on, however its not rendering correctly. I've compared the indices and vertices between the c and ts versions and they appear to match. The code is as follows:
constructor(ctx: WebGLRenderingContext, stacks:number,
slices:number, scale: number){
var vertices: number[] = [];
var normals: number[] = [];
var indices: number[] = [];
var ii: number;
var jj: number;
var v: number;
var u: number;
normals.push(0, 0, 1);
vertices.push(0, 0, scale);
for (ii = 0; ii < slices; ++ii) {
indices.push(0);
indices.push(ii + 1);
}
indices.push(0);
indices.push(1);
for (ii = 1; ii < stacks; ++ii) {
v = ii / stacks;
for (jj = 0; jj < slices; ++jj) {
u = jj / slices;
normals.push.apply(normals, this.shapeNormal(u, v));
vertices.push.apply(vertices, this.shapeVertex(scale, u, v));
indices.push((ii - 1) * slices + (jj + 1));
var index_offset: number = ((ii + 1) === stacks) ? 0 : jj;
var second: number = ii * slices + (index_offset + 1);
//console.log("Offset: " + String(index_offset) + " Value: " + String(second));
indices.push(second);
}
indices.push((ii - 1) * slices + 1);
indices.push(ii * slices + 1);
}
normals.push(0, 0, -1);
vertices.push(0, 0, -scale);
//console.log("Theoretical vertices: " + String(3 * (2 + slices * (stacks - 1))));
//initialise vbos
console.log("Vertices: " + String(vertices.length / 3));
for(var l = 0; l < vertices.length; l += 3)
console.log(vertices[l].toFixed(6) + " " + vertices[l+1].toFixed(6) + " " + vertices[l+2].toFixed(6));
this.vertices = new VertexBufferObject(ctx, 3, vertices.length / 3);
//console.log("Normals: " + String(normals.length));
this.normals = new VertexBufferObject(ctx, 3, normals.length / 3);
console.log("Indices: " + String(indices.length) + " " + indices.toString());
this.indices = new VertexBufferObject(ctx, 1, indices.length);
//populate vbo
ctx.enableVertexAttribArray(0);
ctx.bindBuffer(ctx.ARRAY_BUFFER, this.vertices.buffer);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);
ctx.enableVertexAttribArray(1);
ctx.bindBuffer(ctx.ARRAY_BUFFER, this.normals.buffer);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(normals), ctx.STATIC_DRAW);
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, this.indices.buffer);
ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices),
ctx.STATIC_DRAW);
ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
ctx.disableVertexAttribArray(0);
ctx.disableVertexAttribArray(1);
this.ctx = ctx;
}
private shapeVertex(r: number, u: number, v: number): number[] {
/* Use maths rather than physics spherical coordinate convention */
var theta: number = u * 2.0 * Math.PI;
var phi: number = v * Math.PI;
var vert: number[] = [
r * Math.cos(theta) * Math.sin(phi),
r * Math.sin(theta) * Math.sin(phi),
r * Math.cos(phi)
];
return vert;
}
private shapeNormal(u: number, v: number): number[] {
/* Use maths rather than physics spherical coordinate convention */
var theta: number = u * 2.0 * Math.PI;
var phi: number = v * Math.PI;
var norm: number[] = [
Math.cos(theta) * Math.sin(phi),
Math.sin(theta) * Math.sin(phi),
Math.cos(phi)
];
var mag: number = Math.sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]);
norm[0] /= mag;
norm[1] /= mag;
norm[2] /= mag;
return norm;
}
public draw(shaderProgram: ShaderProgram): void {
//bind and draw vbo's
this.ctx.enableVertexAttribArray(0);
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vertices.buffer);
this.ctx.vertexAttribPointer(shaderProgram.attributes.position,
this.vertices.itemSize, this.ctx.FLOAT, false, 0, 0);
this.ctx.enableVertexAttribArray(1);
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.normals.buffer);
this.ctx.vertexAttribPointer(shaderProgram.attributes.normal,
this.normals.itemSize, this.ctx.FLOAT, false, 0, 0);
this.ctx.bindBuffer(this.ctx.ELEMENT_ARRAY_BUFFER, this.indices.buffer);
this.ctx.drawElements(this.ctx.TRIANGLES, this.indices.numItems,
this.ctx.UNSIGNED_SHORT, 0);
this.ctx.bindBuffer(this.ctx.ELEMENT_ARRAY_BUFFER, null);
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, null);
this.ctx.disableVertexAttribArray(0);
this.ctx.disableVertexAttribArray(1);
}
and a screenshot of the result:
Broken Sphere
Thank you in advance
As TypeScript is just a supersed of Javascript, your problem is probably related to how Javascript handle your code computations.
I'm not sure about your code as you didn't provide the original source.
Assuming your code is correct, you may encounter a floating point approximation error.
I have a wide variety of locations stored in my persistent object that contain latitudes and longitudes in double(43.7389, 7.42577) format. I need to be able to grab the user's latitude and longitude and select all items within, say 1 mile. Walking distance.
I have done this in PHP so I snagged my PHP code and transferred it to Java, where everything plugged in fine until I figured out J2ME doesn't support atan2(double, double). So, after some searching, I find a small snippet of code that is supposed to be a substitute for atan2. Here is the code:
public double atan2(double y, double x) {
double coeff_1 = Math.PI / 4d;
double coeff_2 = 3d * coeff_1;
double abs_y = Math.abs(y)+ 1e-10f;
double r, angle;
if (x >= 0d) {
r = (x - abs_y) / (x + abs_y);
angle = coeff_1;
} else {
r = (x + abs_y) / (abs_y - x);
angle = coeff_2;
}
angle += (0.1963f * r * r - 0.9817f) * r;
return y < 0.0f ? -angle : angle;
}
I am getting odd results from this. My min and max latitude and longitudes are coming back as incredibly low numbers that can't possibly be right. Like 0.003785746 when I am expecting something closer to the original lat and long values (43.7389, 7.42577).
Since I am no master of advanced math, I don't really know what to look for here. Perhaps someone else may have an answer.
Here is my complete code:
package store_finder;
import java.util.Vector;
import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;
import net.rim.blackberry.api.invoke.Invoke;
import net.rim.blackberry.api.invoke.MapsArguments;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
public class nearBy extends MainScreen {
private HorizontalFieldManager _top;
private VerticalFieldManager _middle;
private int horizontalOffset;
private final static long animationTime = 300;
private long animationStart = 0;
private double latitude = 43.7389;
private double longitude = 7.42577;
private int _interval = -1;
private double max_lat;
private double min_lat;
private double max_lon;
private double min_lon;
private double latitude_in_degrees;
private double longitude_in_degrees;
public nearBy()
{
super();
horizontalOffset = Display.getWidth();
_top = new HorizontalFieldManager(Manager.USE_ALL_WIDTH | Field.FIELD_HCENTER)
{
public void paint(Graphics gr)
{
Bitmap bg = Bitmap.getBitmapResource("bg.png");
gr.drawBitmap(0, 0, Display.getWidth(), Display.getHeight(), bg, 0, 0);
subpaint(gr);
}
};
_middle = new VerticalFieldManager()
{
public void paint(Graphics graphics)
{
graphics.setBackgroundColor(0xFFFFFF);
graphics.setColor(Color.BLACK);
graphics.clear();
super.paint(graphics);
}
protected void sublayout(int maxWidth, int maxHeight)
{
int displayWidth = Display.getWidth();
int displayHeight = Display.getHeight();
super.sublayout( displayWidth, displayHeight);
setExtent( displayWidth, displayHeight);
}
};
add(_top);
add(_middle);
Bitmap lol = Bitmap.getBitmapResource("logo.png");
BitmapField lolfield = new BitmapField(lol);
_top.add(lolfield);
Criteria cr= new Criteria();
cr.setCostAllowed(true);
cr.setPreferredResponseTime(60);
cr.setHorizontalAccuracy(5000);
cr.setVerticalAccuracy(5000);
cr.setAltitudeRequired(true);
cr.isSpeedAndCourseRequired();
cr.isAddressInfoRequired();
try{
LocationProvider lp = LocationProvider.getInstance(cr);
if( lp!=null ){
lp.setLocationListener(new LocationListenerImpl(), _interval, 1, 1);
}
}
catch(LocationException le)
{
add(new RichTextField("Location exception "+le));
}
//_middle.add(new RichTextField("this is a map " + Double.toString(latitude) + " " + Double.toString(longitude)));
int lat = (int) (latitude * 100000);
int lon = (int) (longitude * 100000);
String document = "<location-document>" + "<location lon='" + lon + "' lat='" + lat + "' label='You are here' description='You' zoom='0' />" + "<location lon='742733' lat='4373930' label='Hotel de Paris' description='Hotel de Paris' address='Palace du Casino' postalCode='98000' phone='37798063000' zoom='0' />" + "</location-document>";
// Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments( MapsArguments.ARG_LOCATION_DOCUMENT, document));
_middle.add(new SeparatorField());
surroundingVenues();
_middle.add(new RichTextField("max lat: " + max_lat));
_middle.add(new RichTextField("min lat: " + min_lat));
_middle.add(new RichTextField("max lon: " + max_lon));
_middle.add(new RichTextField("min lon: " + min_lon));
}
private void surroundingVenues()
{
double point_1_latitude_in_degrees = latitude;
double point_1_longitude_in_degrees= longitude;
// diagonal distance + error margin
double distance_in_miles = (5 * 1.90359441) + 10;
getCords (point_1_latitude_in_degrees, point_1_longitude_in_degrees, distance_in_miles, 45);
double lat_limit_1 = latitude_in_degrees;
double lon_limit_1 = longitude_in_degrees;
getCords (point_1_latitude_in_degrees, point_1_longitude_in_degrees, distance_in_miles, 135);
double lat_limit_2 = latitude_in_degrees;
double lon_limit_2 = longitude_in_degrees;
getCords (point_1_latitude_in_degrees, point_1_longitude_in_degrees, distance_in_miles, -135);
double lat_limit_3 = latitude_in_degrees;
double lon_limit_3 = longitude_in_degrees;
getCords (point_1_latitude_in_degrees, point_1_longitude_in_degrees, distance_in_miles, -45);
double lat_limit_4 = latitude_in_degrees;
double lon_limit_4 = longitude_in_degrees;
double mx1 = Math.max(lat_limit_1, lat_limit_2);
double mx2 = Math.max(lat_limit_3, lat_limit_4);
max_lat = Math.max(mx1, mx2);
double mm1 = Math.min(lat_limit_1, lat_limit_2);
double mm2 = Math.min(lat_limit_3, lat_limit_4);
min_lat = Math.max(mm1, mm2);
double mlon1 = Math.max(lon_limit_1, lon_limit_2);
double mlon2 = Math.max(lon_limit_3, lon_limit_4);
max_lon = Math.max(mlon1, mlon2);
double minl1 = Math.min(lon_limit_1, lon_limit_2);
double minl2 = Math.min(lon_limit_3, lon_limit_4);
min_lon = Math.max(minl1, minl2);
//$qry = "SELECT DISTINCT zip.zipcode, zip.latitude, zip.longitude, sg_stores.* FROM zip JOIN store_finder AS sg_stores ON sg_stores.zip=zip.zipcode WHERE zip.latitude<=$lat_limit_max AND zip.latitude>=$lat_limit_min AND zip.longitude<=$lon_limit_max AND zip.longitude>=$lon_limit_min";
}
private void getCords(double point_1_latitude, double point_1_longitude, double distance, int degs)
{
double m_EquatorialRadiusInMeters = 6366564.86;
double m_Flattening=0;
double distance_in_meters = distance * 1609.344 ;
double direction_in_radians = Math.toRadians( degs );
double eps = 0.000000000000005;
double r = 1.0 - m_Flattening;
double point_1_latitude_in_radians = Math.toRadians( point_1_latitude );
double point_1_longitude_in_radians = Math.toRadians( point_1_longitude );
double tangent_u = (r * Math.sin( point_1_latitude_in_radians ) ) / Math.cos( point_1_latitude_in_radians );
double sine_of_direction = Math.sin( direction_in_radians );
double cosine_of_direction = Math.cos( direction_in_radians );
double heading_from_point_2_to_point_1_in_radians = 0.0;
if ( cosine_of_direction != 0.0 )
{
heading_from_point_2_to_point_1_in_radians = atan2( tangent_u, cosine_of_direction ) * 2.0;
}
double cu = 1.0 / Math.sqrt( ( tangent_u * tangent_u ) + 1.0 );
double su = tangent_u * cu;
double sa = cu * sine_of_direction;
double c2a = ( (-sa) * sa ) + 1.0;
double x= Math.sqrt( ( ( ( 1.0 /r /r ) - 1.0 ) * c2a ) + 1.0 ) + 1.0;
x= (x- 2.0 ) / x;
double c= 1.0 - x;
c= ( ( (x * x) / 4.0 ) + 1.0 ) / c;
double d= ( ( 0.375 * (x * x) ) -1.0 ) * x;
tangent_u = distance_in_meters /r / m_EquatorialRadiusInMeters /c;
double y= tangent_u;
boolean exit_loop = false;
double cosine_of_y = 0.0;
double cz = 0.0;
double e = 0.0;
double term_1 = 0.0;
double term_2 = 0.0;
double term_3 = 0.0;
double sine_of_y = 0.0;
while( exit_loop != true )
{
sine_of_y = Math.sin(y);
cosine_of_y = Math.cos(y);
cz = Math.cos( heading_from_point_2_to_point_1_in_radians + y);
e = (cz * cz * 2.0 ) - 1.0;
c = y;
x = e * cosine_of_y;
y = (e + e) - 1.0;
term_1 = ( sine_of_y * sine_of_y * 4.0 ) - 3.0;
term_2 = ( ( term_1 * y * cz * d) / 6.0 ) + x;
term_3 = ( ( term_2 * d) / 4.0 ) -cz;
y= ( term_3 * sine_of_y * d) + tangent_u;
if ( Math.abs(y - c) > eps )
{
exit_loop = false;
}
else
{
exit_loop = true;
}
}
heading_from_point_2_to_point_1_in_radians = ( cu * cosine_of_y * cosine_of_direction ) - ( su * sine_of_y );
c = r * Math.sqrt( ( sa * sa ) + ( heading_from_point_2_to_point_1_in_radians * heading_from_point_2_to_point_1_in_radians ) );
d = ( su * cosine_of_y ) + ( cu * sine_of_y * cosine_of_direction );
double point_2_latitude_in_radians = atan2(d, c);
c = ( cu * cosine_of_y ) - ( su * sine_of_y * cosine_of_direction );
x = atan2( sine_of_y * sine_of_direction, c);
c = ( ( ( ( ( -3.0 * c2a ) + 4.0 ) * m_Flattening ) + 4.0 ) * c2a * m_Flattening ) / 16.0;
d = ( ( ( (e * cosine_of_y * c) + cz ) * sine_of_y * c) + y) * sa;
double point_2_longitude_in_radians = ( point_1_longitude_in_radians + x) - ( ( 1.0 - c) * d * m_Flattening );
heading_from_point_2_to_point_1_in_radians = atan2( sa, heading_from_point_2_to_point_1_in_radians ) + Math.PI;
latitude_in_degrees = Math.toRadians( point_2_latitude_in_radians );
longitude_in_degrees = Math.toRadians( point_2_longitude_in_radians );
}
public double atan2(double y, double x) {
double coeff_1 = Math.PI / 4d;
double coeff_2 = 3d * coeff_1;
double abs_y = Math.abs(y)+ 1e-10f;
double r, angle;
if (x >= 0d) {
r = (x - abs_y) / (x + abs_y);
angle = coeff_1;
} else {
r = (x + abs_y) / (abs_y - x);
angle = coeff_2;
}
angle += (0.1963f * r * r - 0.9817f) * r;
return y < 0.0f ? -angle : angle;
}
private Vector fetchVenues(double max_lat, double min_lat, double max_lon, double min_lon)
{
return new Vector();
}
private class LocationListenerImpl implements LocationListener {
public void locationUpdated(LocationProvider provider, Location location) {
if(location.isValid()) {
nearBy.this.longitude = location.getQualifiedCoordinates().getLongitude();
nearBy.this.latitude = location.getQualifiedCoordinates().getLatitude();
//double altitude = location.getQualifiedCoordinates().getAltitude();
//float speed = location.getSpeed();
}
}
public void providerStateChanged(LocationProvider provider, int newState) {
// MUST implement this. Should probably do something useful with it as well.
}
}
}
please excuse the mess. I have the user lat long hard coded since I do not have GPS functional yet. You can see the SQL query commented out to know how I plan on using the min and max lat and long values.
Any help is appreciated.
Thanks
If you are targeting OS 4.6 and above, an atan2 method was added to the MathUtilities class. Otherwise, I'd suggest just Googling around until you find an implementation that works. As Matthew Flaschen suggested, compare the results to what you normally get with a standard atan2 function in J2SE or PHP.
atan2 isn't hard to implement. The definition of what to return based on the 2 arguments is given in the definition. Technically there might be a tiny bit of precision loss from doing the division yourself compared with what might be technically achieveable, but I don't think it will ever matter in rpactice.