Geoserver terrain provider display spikes and cut image - geoserver

I'm playing around with cesiumjs and GeoServer.
I followed the readme from this repo GitHub - kaktus40/Cesium-GeoserverTerrainProvider: plugin to use GeoServer as terrain provider
and able to serve data from GeoServer to cesium, the only problem I'm getting is a spikes edges in the image and black gaps between tiles.
You can see in this image https://ibb.co/yR9Jpr9
I used this site https://srtm.csi.cgiar.org/ to download SRTM data.
I made a pyramid from it using gdal_relite.py, and uploaded it using the imagePyramid plugin.
And I added the bil plugin for GeoServer and made the default encoding to be application/bil16.
The sample of the code I'm using
const terrainProvider = new Cesium.GeoserverTerrainProvider({
service: ‘WMS’,
url: ‘http://localhost:8080/geoserver/elevation/wms’,
layerName: ‘newp’,
xml: ‘http://localhost:8080/geoserver/elevation/wms?SERVICE=WMS&REQUEST=GetCapabilities&tiled=true’,
heightMapWidth: 64,
heightMapHeight: 64,
offset: 0,
highest: 12000,
lowest: -500,
hasStyledImage: false,
waterMask: false,
maxLevel: 11,
formatImage: { format: ‘image/png’, extension: ‘png’ },
formatArray: {
format: ‘image/bil’,
postProcessArray: function (bufferIn, size, highest, lowest, offset) {
var resultat;
var viewerIn = new DataView(bufferIn);
var littleEndianBuffer = new ArrayBuffer(size.height * size.width * 2);
var viewerOut = new DataView(littleEndianBuffer);
if (littleEndianBuffer.byteLength === bufferIn.byteLength) {
// time to switch bytes!!
var temp,
goodCell = 0,
somme = 0;
for (var i = 0; i < littleEndianBuffer.byteLength; i += 2) {
temp = viewerIn.getInt16(i, false) - offset;
if (temp > lowest && temp < highest) {
viewerOut.setInt16(i, temp, true);
somme += temp;
goodCell++;
} else {
var val = goodCell === 0 ? 1 : somme / goodCell;
viewerOut.setInt16(i, val, true);
}
}
resultat = new Int16Array(littleEndianBuffer);
}
return resultat;
},
},
});
Does anyone know how can I fix this issue?

Related

Animation doesn't show steps-in-between

I have created a simple function that would "animate" the cell backcolor at a tap, it works perfectly fine:
Color nOldColor = _grid.BackgroundColor;
for (int i = 0; i <= 100; i += 5)
{
double f = (double)i / (double)100;
Color nNewColor = PCLHelper.BlendColors(nOldColor, Color.Red, f);
_grid.BackgroundColor = nNewColor;
_label1.BackgroundColor = nNewColor;
await Task.Delay(5);
}
_grid.BackgroundColor = nOldColor;
_label1.BackgroundColor = nOldColor;
Now I wanted to do the same with an Animation, but the animation doesn't show the steps "in-between" but rather (as it looks to me) switches to the final color:
private async void animateButtonTouched()
{
int repeatCountMax = 100;
Color nOldColor = _grid.BackgroundColor;
var repeatCount = 0;
_grid.Animate("changeBG", new Animation((val) =>
{
double f = (double)repeatCount / (double)100;
Color nNewColor = PCLHelper.BlendColors(nOldColor, Color.Red, f);
_grid.BackgroundColor = nNewColor;
_label1.BackgroundColor = nNewColor;
}),
5, //duration. I've also tried it with 100. Nothing helped
finished: (val, b) =>
{
repeatCount++;
}, repeat: () =>
{
return repeatCount < repeatCountMax;
});
What am I doing wrong?
"You are making it more difficult than it needs to be." Trademark pending 🍣
The Animate callback is providing the stepping value (or keyframe value). This is a double from 0 to 1 that is called ever X milliseconds (i.e. the length of a single animation frame, 16 default) over the course of X milliseconds (250 default).
So in this example the ShiftToColor gets called 125 times (2000 / 16) with a value that is evenly divided from 0 to 1, thus steps of .008.
var orgColor = aFormsElementInstance.BackgroundColor;
aFormsElementInstance.Animate("changeBG", new Animation((val) =>
{
Color ShiftToColor(Color From, Color To, double pct)
{
var r = From.R + ((To.R - From.R) * val);
var g = From.G + ((To.G - From.G) * val);
var b = From.B + ((To.B - From.B) * val);
return new Color(r, g, b);
}
Device.BeginInvokeOnMainThread(() =>
{
aFormsElementInstance.BackgroundColor = ShiftToColor(orgColor, Color.Red, val);
});
}), 16, 2000);
Results in:

3D Boolean operations with Three CSG

Following the example here:
http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
And using Three.js with https://github.com/chandlerprall/ThreeCSG, I'm trying to do 3D boolean operations on nodes from the model. Like for example if I have a wall with a window, I want to do invert() on that to get just the window.
I have a function that returns all the vertices of the polygons of a node, here's an example of vertices of an object without holes https://pastebin.com/8dhYzPwE.
I'm using ThreeCSG like this:
const geometryThree = new THREE.Geometry();
geometryThree.vertices.push(
...vertices
);
const geometryCsg = new ThreeBSP(geometryThree);
But that's what I'm getting in geometryCsg:
"{
"matrix": {
"elements": {
"0": 1,
"1": 0,
"2": 0,
"3": 0,
"4": 0,
"5": 1,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 1,
"11": 0,
"12": 0,
"13": 0,
"14": 0,
"15": 1
}
},
"tree": {
"polygons": []
}
}"
I think it's because the geometry.faces.length is 0.
How can I make the vertices array to be a proper Three.Geometry such that the faces won't be empty? Geometry.elementsNeedsUpdate doesn't work...
Is there an example that uses polygons of a shape as an array of Vector3s and transforms that to csg?
I just worked on a demo using THREE csg: the Viewer meshes have an indexed array of vertices so you cannot create a BSP directly out of it. Also my code is using a web worker to process the meshes in order to keep the UI responsive with large models, so I need first to send the mesh data to the worker and reconstruct a simple THREE.Mesh on the worker side, the code looks like below:
// Sends component geometry to the web worker
postComponent (dbId) {
const geometry = this.getComponentGeometry(dbId)
const msg = {
boundingBox: this.getComponentBoundingBox(dbId),
matrixWorld: geometry.matrixWorld,
nbMeshes: geometry.meshes.length,
msgId: 'MSG_ID_COMPONENT',
dbId
}
geometry.meshes.forEach((mesh, idx) => {
msg['positions' + idx] = mesh.positions
msg['indices' + idx] = mesh.indices
msg['stride' + idx] = mesh.stride
})
this.worker.postMessage(msg)
}
// get geometry for all fragments in a component
getComponentGeometry (dbId) {
const fragIds = Toolkit.getLeafFragIds(
this.viewer.model, dbId)
let matrixWorld = null
const meshes = fragIds.map((fragId) => {
const renderProxy = this.viewer.impl.getRenderProxy(
this.viewer.model,
fragId)
const geometry = renderProxy.geometry
const attributes = geometry.attributes
const positions = geometry.vb
? geometry.vb
: attributes.position.array
const indices = attributes.index.array || geometry.ib
const stride = geometry.vb ? geometry.vbstride : 3
const offsets = geometry.offsets
matrixWorld = matrixWorld ||
renderProxy.matrixWorld.elements
return {
positions,
indices,
offsets,
stride
}
})
return {
matrixWorld,
meshes
}
}
// On the worker side reconstruct THREE.Mesh
// from received data and create ThreeBSP
function buildComponentMesh (data) {
const vertexArray = []
for (let idx=0; idx < data.nbMeshes; ++idx) {
const meshData = {
positions: data['positions' + idx],
indices: data['indices' + idx],
stride: data['stride' + idx]
}
getMeshGeometry (meshData, vertexArray)
}
const geometry = new THREE.Geometry()
for (var i = 0; i < vertexArray.length; i += 3) {
geometry.vertices.push(vertexArray[i])
geometry.vertices.push(vertexArray[i + 1])
geometry.vertices.push(vertexArray[i + 2])
const face = new THREE.Face3(i, i + 1, i + 2)
geometry.faces.push(face)
}
const matrixWorld = new THREE.Matrix4()
matrixWorld.fromArray(data.matrixWorld)
const mesh = new THREE.Mesh(geometry)
mesh.applyMatrix(matrixWorld)
mesh.boundingBox = data.boundingBox
mesh.bsp = new ThreeBSP(mesh)
mesh.dbId = data.dbId
return mesh
}
function getMeshGeometry (data, vertexArray) {
const offsets = [{
count: data.indices.length,
index: 0,
start: 0}
]
for (var oi = 0, ol = offsets.length; oi < ol; ++oi) {
var start = offsets[oi].start
var count = offsets[oi].count
var index = offsets[oi].index
for (var i = start, il = start + count; i < il; i += 3) {
const a = index + data.indices[i]
const b = index + data.indices[i + 1]
const c = index + data.indices[i + 2]
const vA = new THREE.Vector3()
const vB = new THREE.Vector3()
const vC = new THREE.Vector3()
vA.fromArray(data.positions, a * data.stride)
vB.fromArray(data.positions, b * data.stride)
vC.fromArray(data.positions, c * data.stride)
vertexArray.push(vA)
vertexArray.push(vB)
vertexArray.push(vC)
}
}
}
The complete code of my sample is there: Wall Analyzer and the live demo there.

PHASER ALTARA Struggling with motion paths, enemy ai and animations

Basically I want to make my sprite follow a motion path and depending on its direction it is going, it will play a particular animation. i.e. moving up will display its back, moving left will display the left side of the sprite and so on.
I've tried for hours but to no avail in trying to make this work. I had some luck using prototype but the final game will be using the structure below. ANY help will be appreciated.
/*
* initalise Phaser framework with width:960px, height:540px
*/
var game = new Phaser.Game(960, 540, Phaser.AUTO, 'gameContainer', { preload: preload, create: create, update: update, });
/*
* Preload runs before the game starts. Assets such as images and sounds such be preloaded here.
* A webserver is required to load assets.
*
* Also in this function we set game scale so it full browser width.
*/
function preload() {
// set to scale to full browser width
this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.scale.parentIsWindow = true;
//set the background color so can confirm the game renders in the browser
this.stage.backgroundColor = '#4488cc';
this.game.renderer.renderSession.roundPixels = true;
//preload images & sounds
//game.load.image('key', 'folder/filename.png');
//this.load.image('nazi', 'image/nazi.png');
game.load.spritesheet('nazi', 'images/nazi.png', 128, 128, 6);
this.bmd = null;
this.alien = null;
this.mode = 0;
//Use this website to set enemy movements http://phaser.io/waveforms. Export save data from the console log.
this.points = {
"type":0,"closed":true,"x":[120,120,260,260,200,180,120],"y":[368,108,108,308,308,368,368]
};
this.pi = 0;
this.path = [];
}
/*
* Add game variables here
*/
var nazi;
/*
* Create runs once only when Phaser first loads
* create the game scene by adding objects to the stage
*/
function create() {
bmd = this.add.bitmapData(this.game.width, this.game.height);
bmd.addToWorld();
/*
For testing
this.alien = this.add.sprite(0, 0, 'alien');
this.alien.anchor.set(0.5);
*/
this.nazi = this.add.sprite(0, 0, 'nazi');
this.nazi.anchor.set(0.5);
var py = this.points.y;
/*Original Code
//define the animation
nazi.animations.add('walk');
//start the animation at 30fps
nazi.animations.play('walk', 3, true);
*/
//define the animation
this.nazi.animations.add('walkDown', [2, 3]);
//start the animation at 30fps
this.nazi.animations.play('walkDown', 3, true);
//define the animation
this.nazi.animations.add('walkLR', [4, 5]);
//start the animation at 30fps
this.nazi.animations.play('walkLR', 3, true);
//define the animation
this.nazi.animations.add('walkUp', [0, 1]);
//start the animation at 30fps
this.nazi.animations.play('walkUp', 3, true);
}
function plot() {
this.bmd.clear();
this.path = [];
/*ROTATION CODE*/
var ix = 0;
/**/
//Sets the speed of the sprite
var x = 0.5 / game.width;
//looping through plotting points from x and y array
for (var i = 0; i <= 1; i += x) {
var px = this.math.linearInterpolation(this.points.x, i);
var py = this.math.linearInterpolation(this.points.y, i);
/* ROTATION CODE to follow direction of path*/
var node = { x: px, y: py, angle: 0 };
if (ix > 0)
{
node.angle = this.math.angleBetweenPoints(this.path[ix - 1], node);
}
this.path.push(node);
ix++;
/**/
//this.path.push( { x: px, y: py });
this.bmd.rect(px, py, 1, 1, 'rgba(255, 255, 255, 1)');
}
for (var p = 0; p < this.points.x.length; p++) {
this.bmd.rect(this.points.x[p]-3, this.points.y[p]-3, 6, 6, 'rgba(255, 0, 0, 1)');
}
}
/*
* Update runs continuously. Its the game loop function.
* Add collision detections and control events here
*/
function update() {
plot();
// Reset the players velocity (movement)
//this.nazi = 'nazi';
/* For Testing
this.alien.x = this.path[this.pi].x;
this.alien.y = this.path[this.pi].y;
//ROTATION CODE:
this.alien.rotation = this.path[this.pi].angle;
*/
this.nazi.x = this.path[this.pi].x;
this.nazi.y = this.path[this.pi].y;
//this.nazi.rotation = this.path[this.pi].angle;
this.pi++;
if (this.pi >= this.path.length)
{
this.pi = 0;
}
/*
// Flipping the player image based on the velocity
if(nazi.body.velocity.x > 0){
//player is moving right
nazi.scale.x = -1;
nazi.animations.play('walkLR');
}
else if(nazi.body.velocity.x < 0){
//player is moving left
nazi.scale.x = 1; //flip the image
nazi.animations.play('walkLR');
}
else if (nazi.body.velocity.y < 0){
nazi.animations.play('walkUp');
}
else if(nazi.body.velocity.y > 0){
//player is not moving
nazi.animations.play('walkDown');
}
*/
}

Is there any solution to Firefox 37's poor Canvas rendering performance

I've deliberately provided the version number in the question as this is the kind of question that will go out of date at some point.
Here is a simple animation that will run perfectly smoothly in Chrome and Safari, but will be very jerky in Firefox:
function lerp(a,b,λ) {
return a + λ*(b-a);
}
function random(a,b) {
return lerp( a, b, Math.random() );
}
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
$(document).ready( function()
{
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var balls = new Array(12);
for( var i=0; i<balls.length; i++ )
{
while(true)
{
var density = Math.sqrt( random(1,100) );
var r = random(5, 30);
var x = random( r+1, canvas.width-1 -(r+1) ),
y = random( r+1, canvas.height-1 -(r+1) );
var overlap = false;
for( var j=0; j<i; j++ )
{
var _x = balls[j].x - x,
_y = balls[j].y - y,
d2 = _x*_x + _y*_y,
_r = balls[j].r + r;
if( d2 < _r*_r )
overlap = true;
}
if( overlap )
continue;
balls[i] = {
color : d3.hsl( lerp(0,240,density/10), random(.3,.7), random(.3,.7) ).toString(),
x : x,
y : y,
vx : random(0, 0.2),
vy : random(0, 0.2),
r : r,
advance: function(t) {
this.x += t * this.vx;
this.y += t * this.vy;
}
};
break;
}
};
window.requestAnimationFrame(vsync);
var t_last;
function vsync(t)
{
if( t_last )
render( t - t_last );
t_last = t;
window.requestAnimationFrame(vsync);
}
function render(t_frame)
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle="gray";
ctx.fillRect(0,0, canvas.width, canvas.height);
function advance_all(t) {
balls.forEach( function(b) {
b.advance(t);
});
}
var t_remaining = t_frame;
while(true) {
var hit = get_next_collision( balls, canvas.width, canvas.height );
if( t_remaining < hit.t )
break;
advance_all( hit.t );
t_remaining -= hit.t;
collide_wall( balls[hit.i], hit.wall );
balls[hit.i].advance(.001);
};
advance_all( t_remaining );
// draw balls
balls.forEach( function(ball) {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI*2, true);
ctx.closePath();
ctx.fillStyle = ball.color;
ctx.fill();
});
}
});
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
function get_next_collision(balls,W,H)
{
var winner;
// ball-wall
balls.forEach( function(ball,i)
{
var t = [];
t['L'] = (ball.r - ball.x) / ball.vx; // s.x + t v.x = r
t['T'] = (ball.r - ball.y) / ball.vy;
t['R'] = (W-1-ball.r - ball.x) / ball.vx; // s.x + t v.x = (W-1)-r
t['B'] = (H-1-ball.r - ball.y) / ball.vy;
// get index of smallest positive t
var LR = t['L'] >= 0 ? 'L' : 'R',
TB = t['T'] >= 0 ? 'T' : 'B',
wall = t[LR] < t[TB] ? LR : TB;
if( ! winner || ( t[wall] <= winner.t ) )
winner = {
t : t[wall],
i : i,
wall: wall
};
});
return winner;
}
function collide_wall( A, wall )
{
if( wall == 'L' || wall == 'R' )
A.vx *= -1;
else
A.vy *= -1;
}
html, body {
width: 100%;
height: 100%;
margin: 0px;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/1.5.1/math.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<canvas id="myCanvas">
<!-- Insert fallback content here -->
</canvas>
Why is Firefox performing significantly worse than its competitors?
If I take the number of balls to 500 Chrome is still smooth, Firefox is seriously choppy.
If I take the number of balls down to 1 Firefox is still burring it.
Another experiment I did was applying a fixed velocity increment each frame, so that the smoothness of the animation accurately reflects the evenness of the render callback. This showed Firefox to be all over the place. Chrome on the other hand was smooth.
If there is sufficient interest, I can provide a snippet for that also and maybe tidy up the first one so that it offers a slider to modify the ball count.
As far as I can see, (1) Firefox definitely isn't giving us a genuine VSYNC callback, I suspect it is just using a timer, (2) even correcting for that by manually calculating elapsed time for each frame, it burrs the animation, maybe suggesting that it sometimes the callback fires in time to catch the VSYNC and sometimes it misses the boat, (3) there is an additional compositing hit that is disproportionate compared with Chrome.
Is there anything to be done about this?
EDIT: I found this question from four years ago! Poor performance of html5 canvas under firefox -- please don't mark this question as the duplicate unless it is certain that the answer to that question is still the only relevant answer four years later. I've deliberately included the version number in the question, as the question pertains specifically to the current version.

Telerik RadEditor Image Manager Window Not Displaying Properly

I am using the Telerik RadEditor and am seeing some strange behavior with the Image Manager window, shown below.
The tabs such as SiteCopy, Body Setup, Header Setup, etc. are all from the page that should be behind the window, yet they are somehow showing through. Clicking and dragging the window to another location on the screen fixes that issue, however, the window cannot be closed using either the X or Cancel. This only seems to happen in Chrome when I am zoomed in a bit on the page. Is this a bug with the Image Manager or is there something that can be done to prevent this behavior?
Thanks
Try the ideas from this thread: http://www.telerik.com/community/forums/button-click-fails-(sometimes)
Chrome 39 broke the internet again because it started returning decimal values for properties that used to be integers, which can cause script errors.
Try the following:
use a RadScriptManager on the main page
The script override from the thread abocve could be the solution you are looking for:
if (document.documentElement.getBoundingClientRect) {
$telerik.originalGetLocation = function (element) {
var e = Function._validateParams(arguments, [
{ name: "element", domElement: true }
]);
if (e) throw e;
if (element.self || element.nodeType === 9 ||
(element === document.documentElement) ||
(element.parentNode === element.ownerDocument.documentElement)) {
return new Sys.UI.Point(0, 0);
}
var clientRect = element.getBoundingClientRect();
if (!clientRect) {
return new Sys.UI.Point(0, 0);
}
var documentElement = element.ownerDocument.documentElement,
offsetX = Math.round(clientRect.left) + documentElement.scrollLeft,
offsetY = Math.round(clientRect.top) + documentElement.scrollTop;
if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
try {
var f = element.ownerDocument.parentWindow.frameElement || null;
if (f) {
var offset = (f.frameBorder === "0" || f.frameBorder === "no") ? 2 : 0;
offsetX += offset;
offsetY += offset;
}
}
catch (ex) {
}
if (Sys.Browser.version === 7 && !document.documentMode) {
var body = document.body,
rect = body.getBoundingClientRect(),
zoom = (rect.right - rect.left) / body.clientWidth;
zoom = Math.round(zoom * 100);
zoom = (zoom - zoom % 5) / 100;
if (!isNaN(zoom) && (zoom !== 1)) {
offsetX = Math.round(offsetX / zoom);
offsetY = Math.round(offsetY / zoom);
}
}
if ((document.documentMode || 0) < 8) {
offsetX -= documentElement.clientLeft;
offsetY -= documentElement.clientTop;
}
}
offsetX = Math.round(offsetX);
offsetY = Math.round(offsetY);
return new Sys.UI.Point(offsetX, offsetY);
};
}

Resources