When I drag the svg(red) to another position on the screen, the cursor mouse loses the original angular position (lag) and points to blank area ... I used a var dx and dy in "var point e.clientx" to fix it, unsuccessfully ... any suggestions?
code: http://jsfiddle.net/rebecavascon/evgLhdz3/2/
show: http://jsfiddle.net/rebecavascon/evgLhdz3/2/show/
function updateSVG(e) {
if (follow) {
var centerPoint = new Point(center[0].getAttribute("cx"), center[0].getAttribute("cy"));
var point = new Point(e.clientX, e.clientY);
var angle = Math.round(100 * getAngleFromPoint(point, centerPoint)) / 100;
var distance = Math.round(getDistance(point, centerPoint));
var d = "M " + centerPoint.X + " " + centerPoint.Y + " L " + point.X + " " + point.Y;
path.attr("d", d);
txt.attr("x", point.X);
txt.attr("y", point.Y);
txt.html(distance + arrows + " (" + angle + degree + ")");
txt.attr("transform", "rotate(" + angle + " " + point.X + " " + point.Y + ")");
dynamic.attr("r", distance);
}
fitSVG();
}
Creating an offset worked for my testing.
Code: http://jsfiddle.net/Twisty/8zx8p2wf/19/
Working: http://jsfiddle.net/Twisty/8zx8p2wf/19/show/
Added Function getCenter()
function getCenter(target) {
var b, x, y, w, h, cx, cy;
b = target[0].getBoundingClientRect();
console.log(target, b);
x = b.x;
y = b.y;
w = b.width;
h = b.height;
cx = x + (w / 2);
cy = y + (h / 2);
console.log(x, y, w, h, cx, cy);
return {
X: cx,
Y: cy
};
}
This gets the true center of an SVG Object. Looks like the cx and cy attributes do not get updated.
Updated function updateSVG()
function updateSVG(e) {
if (follow) {
var centerPoint = getCenter(center);
var point = new Point(e.clientX, e.clientY);
var angle = Math.round(100 * getAngleFromPoint(point, centerPoint)) / 100;
var distance = Math.round(getDistance(point, centerPoint));
var od = {
p: {
X: point.X - offset.X,
Y: point.Y - offset.Y
},
cp: {
X: centerPoint.X - offset.X,
Y: centerPoint.Y - offset.Y
}
};
var d = "M" + od.p.X + "," + od.p.Y + " L" + od.cp.X + "," + od.cp.Y;
path.attr("d", d);
txt.attr("x", point.X);
txt.attr("y", point.Y);
txt.html(distance + arrows + " (" + angle + degree + ")");
txt.attr("transform", "rotate(" + angle + " " + point.X + " " + point.Y + ")");
dynamic.attr("r", distance);
}
fitSVG();
}
This uses a new offset constant variable and the correct center points.
JavaScript
$(function() {
var center = $("#center"),
dynamic = $("#dynamic"),
path = $("#deg"),
svg = $("svg"),
txt = $("#txt"),
svgNS = svg[0].namespaceURI,
degree = String.fromCharCode(176),
arrows = String.fromCharCode(845),
follow = true,
startPos,
endPos,
offset = {
X: 0,
Y: 0
};
function Point(x, y) {
return {
"X": x,
"Y": y
};
}
function getCenter(target) {
var b, x, y, w, h, cx, cy;
b = target[0].getBoundingClientRect();
console.log(target, b);
x = b.x;
y = b.y;
w = b.width;
h = b.height;
cx = x + (w / 2);
cy = y + (h / 2);
console.log(x, y, w, h, cx, cy);
return {
X: cx,
Y: cy
};
}
// Credits goes to Stackoverflow: http://stackoverflow.com/a/14413632
function getAngleFromPoint(point, centerPoint) {
var dy = (point.Y - centerPoint.Y),
dx = (point.X - centerPoint.X);
var theta = Math.atan2(dy, dx);
var angle = (((theta * 180) / Math.PI)) % 360;
angle = (angle < 0) ? 360 + angle : angle;
return angle;
}
// Credits goes to http://snipplr.com/view/47207/
function getDistance(point1, point2) {
var xs = 0;
var ys = 0;
xs = point2.X - point1.X;
xs = xs * xs;
ys = point2.Y - point1.Y;
ys = ys * ys;
return Math.sqrt(xs + ys);
}
function fitSVG() {
var width = window.innerWidth,
height = window.innerHeight;
svg.width(width);
svg.height(height);
}
function updateSVG(e) {
if (follow) {
//var centerPoint = new Point(center[0].getAttribute("cx"), center[0].getAttribute("cy"));
var centerPoint = getCenter(center);
var point = new Point(e.clientX, e.clientY);
var angle = Math.round(100 * getAngleFromPoint(point, centerPoint)) / 100;
var distance = Math.round(getDistance(point, centerPoint));
var od = {
p: {
X: point.X - offset.X,
Y: point.Y - offset.Y
},
cp: {
X: centerPoint.X - offset.X,
Y: centerPoint.Y - offset.Y
}
};
var d = "M" + od.p.X + "," + od.p.Y + " L" + od.cp.X + "," + od.cp.Y;
$("#mouse").html(e.clientX + "," + e.clientY);
$("#svgPos").html(svg.position().left + "," + svg.position().top);
$("#offset").html(offset.X + "," + offset.Y);
$("#centerPoint").html(centerPoint.X + "," + centerPoint.Y);
$("#point").html(point.X + "," + point.Y);
$("#path").html(d);
$("#angle").html(angle);
$("#distance").html(distance);
path.attr("d", d);
txt.attr("x", point.X);
txt.attr("y", point.Y);
txt.html(distance + arrows + " (" + angle + degree + ")");
txt.attr("transform", "rotate(" + angle + " " + point.X + " " + point.Y + ")");
dynamic.attr("r", distance);
}
fitSVG();
}
grid_size = 10;
svg
.mousemove(updateSVG)
.click(function() {
follow = !follow;
return true;
});
$(".img").draggable({
handle: "svg",
classes: {
"ui-draggable-dragging": "opac"
},
cursor: "grab",
grid: [grid_size, grid_size],
start: function(e, ui) {
$(this).find(".text").hide();
follow = false;
startPos = ui.position;
},
stop: function() {
follow = true;
endPos = svg.position();
offset.X = endPos.left;
offset.Y = endPos.top;
}
});
});
Through testing, I adjusted the draggable a little bit, such that, the div.img wrapper is the draggable and the svg inside is the handle. I'm not sure if there is a benefit here, yet I didn't want it to go unnoticed.
Related
I've been trying to look over the Konva shape library and haven't found a stroke reapeating pattern method. I've been trying to look for a way to implement https://stackoverflow.com/a/32323610/20557085 into the shape's sceneFunc, but ended up with a static version that keeps itself in the top right corner of the canvas at all times, even if the canvas/camera is moved/dragged.
The end-goal would be to have a image that repeats itself following a line's bezier curve of points, that I can change the width of.
The question would be if there is something I am missing that is already a part of Konva, or if I should continue to trial my way through the sceneFunc?
The class component used in my attempt, that ended up static:
import React, { Component } from 'react';
import { createRoot } from 'react-dom/client';
import { Stage, Layer, Image, Shape } from 'react-konva';
var PI = Math.PI;
class URLImageStroke extends React.Component {
constructor(props) {
super(props)
this.state = {
image: null,
points: [{ x: 0, y: 0 }, { x: 100, y: 100 }, { x: 150, y: 50 }, { x: 200, y: 200 }]
};
}
componentDidMount() {
this.loadImage();
this.getPoints()
}
loadImage() {
// save to "this" to remove "load" handler on unmount
this.image = new window.Image();
this.image.src = this.props.src;
this.image.addEventListener('progress', (e) => console.log(e))
this.image.addEventListener('load', this.handleLoad);
}
handleLoad = () => {
this.setState({
image: this.image,
});
};
getPoints = () => {
let points = [];
//for (let i = 0; this.state.points.length > i; i++) {
const s = this.state.points[0];
const c1 = this.state.points[1];
const c2 = this.state.points[2];
const e = this.state.points[3];
for (var t = 0; t <= 100; t += 0.25) {
var T = t / 100;
// plot a point on the curve
var pos = getCubicBezierXYatT(s, c1, c2, e, T);
// calculate the tangent angle of the curve at that point
var tx = bezierTangent(s.x, c1.x, c2.x, e.x, T);
var ty = bezierTangent(s.y, c1.y, c2.y, e.y, T);
var a = Math.atan2(ty, tx) - PI / 2;
// save the x/y position of the point and the tangent angle
// in the points array
points.push({
x: pos.x,
y: pos.y,
angle: a
});
}
this.setState({
points: points
});
}
render() {
return (
<Shape
x={50}
y={50}
width={this.props?.width}
height={this.props?.height}
image={this.state.image}
points={this.state?.points}
sceneFunc={(ctx, shape) => {
const img = shape.attrs.image;
if (!img) {
console.log("no image")
return;
}
const points = shape.attrs.points;
if (!points) {
console.log("no points")
return;
}
// Note: increase the lineWidth if
// the gradient has noticable gaps
ctx.lineWidth = 8;
ctx.strokeStyle = 'skyblue';
let sliceCount = 0;
// draw a gradient-stroked line tangent to each point on the curve
for (let i = 0; i < points.length; i++) {
let p = points[i];
ctx.translate(p.x, p.y);
ctx.rotate(p.angle - PI / 2);
// draw multiple times to fill gaps on outside of rope slices
ctx.drawImage(img, sliceCount, 0, 1, img.height, 0, 0, 1, img.height);
ctx.drawImage(img, sliceCount, 0, 1, img.height, 0, 0, 1, img.height);
ctx.drawImage(img, sliceCount, 0, 1, img.height, 0, 0, 1, img.height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
++sliceCount;
if (sliceCount > (img.width - 1)) { sliceCount = 0; }
}
//ctx.strokeShape(this);
}
}
/>
);
}
}
//////////////////////////////////////////
// helper functions
//////////////////////////////////////////
// calculate one XY point along Cubic Bezier at interval T
// (where T==0.00 at the start of the curve and T==1.00 at the end)
function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
return ({ x: x, y: y });
}
// cubic helper formula at T distance
function CubicN(T, a, b, c, d) {
var t2 = T * T;
var t3 = t2 * T;
return a + (-a * 3 + T * (3 * a - a * T)) * T
+ (3 * b + T * (-6 * b + b * 3 * T)) * T
+ (c * 3 - c * 3 * T) * t2
+ d * t3;
}
// calculate the tangent angle at interval T on the curve
function bezierTangent(a, b, c, d, t) {
return (3 * t * t * (-a + 3 * b - 3 * c + d) + 6 * t * (a - 2 * b + c) + 3 * (-a + b));
};
export default URLImageStroke;
I am having column graph which contains positive and negative values column graph, I need to give the border radius top only for the positive and negative Graph. But if I'm trying to add the border radius top for the negative column graph it was not working. Kindly let me know how to give the only border radius top for negative column graph using highcharts in react js.
refer image here
For example ,in the image provided, for I want border radius at -5% for negative value .For positive value I want border radius at top of bar.
I prepared a custom code that adds the wanted border radius for positive value - on the top, for negative - on the bottom of the column.
$(function() {
'use strict';
(function(factory) {
if (typeof module === 'object' && module.exports) {
module.exports = factory;
} else {
factory(Highcharts);
}
}(function(Highcharts) {
(function(H) {
H.wrap(H.seriesTypes.column.prototype, 'translate', function(proceed) {
const options = this.options;
const topMargin = options.topMargin || 0;
const bottomMargin = options.bottomMargin || 0;
proceed.call(this);
H.each(this.points, function(point) {
console.log(point)
if (options.customRadius) {
const w = point.shapeArgs.width;
const h = point.shapeArgs.height;
const x = point.shapeArgs.x;
const y = point.shapeArgs.y;
let radiusTopLeft,
radiusTopRight,
radiusBottomRight,
radiusBottomLeft;
if (point.y > 0) {
radiusTopLeft = H.relativeLength(options.customRadius, w);
radiusTopRight = H.relativeLength(options.customRadius, w);
radiusBottomLeft = 0;
radiusBottomRight = 0;
} else {
radiusTopLeft = 0;
radiusTopRight = 0;
radiusBottomRight = H.relativeLength(options.customRadius, w);
radiusBottomLeft = H.relativeLength(options.customRadius, w);
}
const maxR = Math.min(w, h) / 2
radiusTopLeft = radiusTopLeft > maxR ? maxR : radiusTopLeft;
radiusTopRight = radiusTopRight > maxR ? maxR : radiusTopRight;
radiusBottomRight = radiusBottomRight > maxR ? maxR : radiusBottomRight;
radiusBottomLeft = radiusBottomLeft > maxR ? maxR : radiusBottomLeft;
point.dlBox = point.shapeArgs;
point.shapeType = 'path';
point.shapeArgs = {
d: [
'M', x + radiusTopLeft, y + topMargin,
'L', x + w - radiusTopRight, y + topMargin,
'C', x + w - radiusTopRight / 2, y, x + w, y + radiusTopRight / 2, x + w, y + radiusTopRight,
'L', x + w, y + h - radiusBottomRight,
'C', x + w, y + h - radiusBottomRight / 2, x + w - radiusBottomRight / 2, y + h, x + w - radiusBottomRight, y + h + bottomMargin,
'L', x + radiusBottomLeft, y + h + bottomMargin,
'C', x + radiusBottomLeft / 2, y + h, x, y + h - radiusBottomLeft / 2, x, y + h - radiusBottomLeft,
'L', x, y + radiusTopLeft,
'C', x, y + radiusTopLeft / 2, x + radiusTopLeft / 2, y, x + radiusTopLeft, y,
'Z'
]
};
}
});
});
}(Highcharts));
}));
Demo: http://jsfiddle.net/BlackLabel/okn8qhdb/
https://konvajs.org/api/Konva.Filters.html
in this link the sharpness filter is not available
Konva doesn't have such a filter in its core. You have to implement it manually.
For that use case, you can write your own custom filter. See custom filters docs.
I tried to use that sharpen implementation: https://gist.github.com/mikecao/65d9fc92dc7197cb8a7c
// noprotect
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
const layer = new Konva.Layer();
stage.add(layer);
function Sharpen(srcData) {
const mix = 1;
const w = srcData.width;
const h = srcData.height;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
var x, sx, sy, r, g, b, a, dstOff, srcOff, wt, cx, cy, scy, scx,
weights = [0, -1, 0, -1, 5, -1, 0, -1, 0],
katet = Math.round(Math.sqrt(weights.length)),
half = (katet * 0.5) | 0,
dstData = ctx.createImageData(w, h),
dstBuff = dstData.data,
srcBuff = srcData.data,
y = h;
while (y--) {
x = w;
while (x--) {
sy = y;
sx = x;
dstOff = (y * w + x) * 4;
r = 0;
g = 0;
b = 0;
a = 0;
for (cy = 0; cy < katet; cy++) {
for (cx = 0; cx < katet; cx++) {
scy = sy + cy - half;
scx = sx + cx - half;
if (scy >= 0 && scy < h && scx >= 0 && scx < w) {
srcOff = (scy * w + scx) * 4;
wt = weights[cy * katet + cx];
r += srcBuff[srcOff] * wt;
g += srcBuff[srcOff + 1] * wt;
b += srcBuff[srcOff + 2] * wt;
a += srcBuff[srcOff + 3] * wt;
}
}
}
dstBuff[dstOff] = r * mix + srcBuff[dstOff] * (1 - mix);
dstBuff[dstOff + 1] = g * mix + srcBuff[dstOff + 1] * (1 - mix);
dstBuff[dstOff + 2] = b * mix + srcBuff[dstOff + 2] * (1 - mix);
dstBuff[dstOff + 3] = srcBuff[dstOff + 3];
}
}
for(var i = 0; i < dstData.data.length; i++) {
srcData.data[i] = dstData.data[i];
}
}
Konva.Image.fromURL('https://i.imgur.com/ktWThtZ.png', img => {
img.setAttrs({filters: [Sharpen]});
img.cache();
layer.add(img);
layer.draw();
});
Demo: https://jsbin.com/tejalusano/1/edit?html,js,output
I've map image (1816 x 8160) having following lat/lon of corners.
TopLeft: (-73.9308,40.8883)
TopRight: (-73.8584,40.858)
BottomLeft: (-74.0665,40.7024)
BottomRight: (-73.9944,40.6718)
Map is not true north and rotated at 28.34, also its UTM Zone 18N (78W to 72W). Here are further details about this map taken from PDF Maps iOS app.
Size (pixels): 1816 x 6160
Pixel Resolution: 3.829 meters
Bounds (pixels): (-1624, -3518) x (7866, 7719)
PROJCS["WGS 84 / UTM zone 18N",
GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
TOWGS84[0,0,0,0,0,0,0],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-75],
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",0],
UNIT["metre",1,
AUTHORITY["EPSG","9001"]],
AXIS["Easting",EAST],
AXIS["Northing",NORTH],
AUTHORITY["EPSG","32618"]]
How to convert lat/lon to x y and vice versa?
Any help will be much appreciated.
Thanks in advance.
var dot_size = 15;
var longitude_shift = 0; //-28.34; // number of pixels your map's prime meridian is off-center.
var x_pos = 0; //54;
var y_pos = 0; //19;
var map_width = 1380; //1816; //430;
var map_height = 4682; //6160; //332;
var half_dot = Math.floor(dot_size / 2);
// Converts from degrees to radians.
Math.radians = function(degrees) {
return degrees * Math.PI / 180;
};
// Converts from radians to degrees.
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
/* N 40.88839 -73.93071 //-73.9308
E 40.85789 -73.85843 //40.858 -73.8584
W 40.70228 -74.06652 //40.7024 -74.0665
S 40.67185 -73.99437 //40.6718 -73.9944 */
var bottomX = 40.67185;
var bottomY = -73.99437;
var topX = 40.88839; //-73.9308; //-73.9308,40.8883
var topY = -73.93071;
var degreesPerPixelX = (bottomX - topX) / map_width; //0.07225 / map_width;
var degreesPerPixelY = (bottomY - topY) / map_height; //0.18605/ map_height;
// These should roughly box Germany - use the actual values appropriate to your image
var minLat = bottomX;
var minLong = bottomY;
var maxLat = topX;
var maxLong = topY;
// Map image size (in points)
var mapSize = {'width': map_width, 'height': map_height};
// Determine the map scale (points per degree)
var xScale = mapSize.width / (maxLong - minLong);
var yScale = mapSize.height / (maxLat - minLat);
var south = Math.radians(40.67185); //lat 47.2
var north = Math.radians(40.88839); //lat 55.2
var west = Math.radians(-74.06652); //long 5.8
var east = Math.radians(-73.85843); //long 15.2
// Formula for mercator projection y coordinate:
function mercY(lat) { return Math.log(Math.tan(lat/2 + Math.PI/4)); }
// Some constants to relate chosen area to screen coordinates
var ymin = mercY(south);
var ymax = mercY(north);
var xFactor = mapSize.width/(east - west);
var yFactor = mapSize.height/(ymax - ymin);
var mapLonLeft = -74.06652; //9.8;
var mapLonRight = -73.85843; //10.2;
var mapLonDelta = mapLonRight - mapLonLeft;
mapLatBottom = 40.67185; //53.45;
mapLatBottomRadian = mapLatBottom * Math.PI / 180;
function convertGeoToPixel(lat, lon)
{
pX = (lon - mapLonLeft) * (mapSize.width / mapLonDelta);
lat1 = lat * Math.PI / 180;
worldMapWidth = ((mapSize.width / mapLonDelta) * 360) / (2 * Math.PI);
mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomRadian)) / (1 - Math.sin(mapLatBottomRadian))));
pY = mapSize.height - ((worldMapWidth / 2 * Math.log((1 + Math.sin(lat1)) / (1 - Math.sin(lat1)))) - mapOffsetY);
return 'x:'+pX+', y:'+pY;
}
function convertPixelToGeo(tx, ty)
{
/* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI */
var worldMapRadius = mapSize.width / mapLonDelta * 360/(2 * Math.PI);
var mapOffsetY = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian)) ));
var equatorY = mapSize.height + mapOffsetY;
var a = (equatorY-ty)/worldMapRadius;
var lat = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
var long = mapLonLeft+tx/mapSize.width*mapLonDelta;
return 'lat:'+lat+', lng:'+long;
}
function draw_point(x, y) {
dot = '<div style="position:absolute;width:' + dot_size + 'px;height:' + dot_size + 'px;top:' + y + 'px;left:' + x + 'px;background:#00ff00"></div>';
document.body.innerHTML += dot;
}
function plot_point(lat, lng) {
spotLat = lat;
spotLong = lng;
// Mercator projection
// longitude: just scale and shift
x = (map_width * (180 + lng) / 360) % map_width + longitude_shift;
// latitude: using the Mercator projection
lat1 = lat * Math.PI / 180; // convert from degrees to radians
y = Math.log(Math.tan((lat1/2) + (Math.PI/4))); // do the Mercator projection (w/ equator of 2pi units)
y = (map_height / 2) - (map_width * y / (2 * Math.PI)) + y_pos; // fit it to our map
x -= x_pos;
y -= y_pos;
// position of map image for point
//var newXY = 'x:' (spotLong - minLong) * xScale + ', y:' + (spotLat - minLat) * yScale +'<br/>';
//var y = (spotLat - minLat) * yScale;
//alert('x: ' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y: ' + kavraY(Math.radians(lat),Math.radians(lng)));
strText = 'kavra x:' + kavraX(Math.radians(lat),Math.radians(lng)) + ', y:' + kavraY(Math.radians(lat),Math.radians(lng)) + '<br/>';
strText += 'x:' + x + ', y:' + y + '<br/>';
strText += 'x:'+(spotLong - minLong) * xScale +', y:' + (spotLat - minLat) * yScale +'<br/>';
strText += 'x:'+((Math.radians(lng) - west)*xFactor)+' ,y:'+((ymax - mercY(Math.radians(lat)))*yFactor)+'<br/>';
strText += convertGeoToPixel(lat,lng)+'<br/>' ;
//floatingDiv = '<div style="position:fixed;top:10px;left:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#leftDiv').html(strText);
draw_point(x - half_dot, y - half_dot);
}
function kavraX (latitude, longitude) // Kavra for Kavrayskiy
// formula from http://en.wikipedia.org/wiki/Kavrayskiy_VII_projection
{
return ((3 * longitude) / 2 * Math.PI)*Math.sqrt(Math.pow(Math.PI, 2)/3 - Math.pow(latitude, 2));
}
function kavraY (latitude, longitude)
{
return latitude*-1;
}
$(document).ready(function() {
//-73.949321, 40.796997
plot_point(40.764296, -73.973027);
$('img').click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLon = topX + relativeX * degreesPerPixelX;
var clickedLat = bottomY + relativeY * degreesPerPixelY;
alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
});
$('#parentDiv').mousemove(function(e) {
var offset = $('img').offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
var clickedLat = topX + relativeX * degreesPerPixelX;
var clickedLon = topY + relativeY * degreesPerPixelY;
//alert(relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon);
var strText = relativeX+':'+relativeY+' lat:'+clickedLat+", lon:"+clickedLon+'<br/>';
strText += 'lat:'+(relativeY / yScale + minLat)+', long:'+(relativeX / xScale + minLong)+'<br/>';
strText += convertPixelToGeo(relativeX,relativeY)+'<br/>';
//floatingDiv = '<div style="position:fixed;top:10px;right:10px;">'+strText+'</div>';
//document.body.innerHTML += floatingDiv;
$('#rightDiv').html(strText);
});
});
/*$(function() {
$("#test").click(function(e) {
var offset = $(this).offset();
var relativeX = (e.pageX - offset.left);
var relativeY = (e.pageY - offset.top);
alert(relativeX+':'+relativeY);
$(".position").val("afaf");
});
});*/
function onClick (evt) {
alert(evt.pageX +' '+ evt.pageY);
var x = getEventOffsetFromImageLeft(evt);
var y = getEventOffsetFromImageTop(evt);
var clickedLon = topX + x * degreesPerPixelX;
var clickedLat = bottomY + y * degreesPerPixelY;
}
</script>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<!-- onload="plot_point(40.756, -73.986)" -->
<body >
<div id='parentDiv'>
<!-- image found at http://i.stack.imgur.com/BXgSw.jpg -->
<img src="http://i.stack.imgur.com/BXgSw.jpg" style="position:absolute;top:0px;left:0px" >
<div id="leftDiv" style="position:fixed;top:10px;left:10px;"></div>
<div id="rightDiv" style="position:fixed;top:10px;right:10px;"></div>
</div>
</body>
</html>
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.