Polyline not showing, it does show when chopped in smaller lines - javascript

I'm trying to show a line but when I initiate the polyline like this nothing shows:
var geopositions = [];
for (var i = 0; i < c.geo.length; i++) {
var g = c.geo[i];
geopositions.push(parseFloat(g.lon));
geopositions.push(parseFloat(g.lat));
}
var line = {
positions: Cesium.Cartesian3.fromDegreesArray(geopositions),
width: 1,
id: "C" + c.id,
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.fromBytes(255, 0, 0, 255)
}),
show: true
}
var coll = new Cesium.PolylineCollection();
coll.add(line);
primitives.add(coll);
So I thought I'd try to draw lines between all the points of the line (the points in c.geo) like so:
var collection = new Cesium.PolylineCollection();
var prev = null;
for (var j = 0; j < c.geo.length; j++) {
var geo = c.geo[j];
if (prev) {
collection.add(
{
positions: Cesium.Cartesian3.fromDegreesArray([
parseFloat(prev.lon), parseFloat(prev.lat),
parseFloat(geo.lon), parseFloat(geo.lat)]),
width: 2,
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.fromBytes(0, 180, 0, 255)
})
}
);
}
prev = geo;
}
primitives.add(collection);
For some reason this does show the line. I can't find the reason why this would be the case and don't understand why a list of lines does show and a standard polyline doesn't show. Does anyone know how to show the line without chopping the line up in small polylines?

Cesium is supposed to handle the case you described. You are most likely running into some form of this bug; which has been fixed with this pull request.

I fixed the problem.
Apparently the Cesium.Polyline doesn't appreciate two consecutive coordinates (both lat and lon) that are exactly the same. The problem seems to be solved by removing the extra coordinates.

Related

From an array of objects, I want to pick a random object from the array and set one of that object's variables

I have an array named grid. Stored in that array is an object, cell. I want to set one of cell's variables(isBomb) to true.
I know that this isn't quite how to do it, but here is my(nonfunctioning implementation).
When I try to run it, I get this error message: Main, line 32:Cannot set property '288' of undefined I assume that's because I formatted it wrong. Could anyone help?
for(var i in grid){
for(var j=0; j<bombAmount; j++){
this.isBomb[floor(random(grid.length))]=true;
}
This is in javascript, with the p5.js library.
Openprocessing link
You can use Math.random() to achieve this. For example:
const grid = [{
cellId: 1
}, {
cellId: 2
}, {
cellId: 3
}, {
cellId: 4
}, {
cellId: 5
}, {
cellId: 6
}, {
cellId: 7
}, {
cellId: 8
}, {
cellId: 9
}, {
cellId: 10
}];
function pickRandomCell() {
return grid[Math.floor(Math.random() * grid.length)];
}
for (let i = 0; i < 50; i++) {
console.dir(pickRandomCell());
}
As the answer above, do Math.random() and update the cell like this:
// Do a loop to apply each bomb to a cell
for (let i = 0; i < bombAmount; i++) {
const randomPosition = Math.round(Math.random() * (grid.length -1));
// Select random cell from grid, and update the "isBomb" to true
grid[randomPosition].isBomb = true;
}
There are quite a few issues with the code that this question doesn't address.
I will start with the simplest question from the title: picking a random object from the an array. The existings answers already address this. I wanted to point out that random() in p5 can also take an array as an argument and returns a random item from that array, as you can see in the reference example:
function setup(){
let words = ['apple', 'bear', 'cat', 'dog'];
let word = random(words); // select random word
console.log(word);
createCanvas(100, 100);
text(word, 10, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
Back to the snippet you posted:
for(var i in grid){
for(var j=0; j<bombAmount; j++){
this.isBomb[floor(random(grid.length))]=true;
}
}
In the context above this will not point to an individual cell.
You might be looking at something like grid[i].isBomb = true instead.
isBomb is a boolean property of Cell hence the errors when trying to access it via array access notation.
The connection between bombAmount and isBomb is unclear.
Perhaps you meant to use something like the bombsFound array returned by checkArea() somehow ?
If you want to pick a random cell to have a bomb or not you could something like:
for(let i = 0; i < grid.length; i++){
grid[i].isBomb = random(0.0, 1.0) > 0.5;
}
the example above sets a psuedo random chance of 50/50 that a cell will be a bomb or not.
The Cell constructor actually accepts isBomb as it's last argument:
function Cell(x, y, bombNum, clicked, isBomb)
Therefore you could skip the loop completely and simply randomly assign isBomb when populating grid:
for (var y = 0; y < rows; y++) {
for (var x = 0; x < cols; x++) {
var cell = new Cell(x, y, index(x, y), false, random(0.0, 1.0) > 0.5);
grid.push(cell);
}
}
Currently it looks like you're not passing the expected arguments to the Cell constructor:
var cell = new Cell(x, y, false);
These are just a few of the issues and points out that you may not fully understand the code you're trying to modify. I recommend slowing down, stepping back for a second and with pen an paper figure out what you're trying to achieve. With the clear goals, break them down into very simple individual steps, solve one step at a time, then start integrating the tested individual steps into the larger program.
Update based on the clarification in the comment bellow you could easily do something like:
for(let i = 0; i < bombAmount; i++){
grid[i].isBomb = random(0.0, 1.0) > 0.5;
}
However this won't guarantee 20 bombs, but a 50-50 chance that the 1st 20 cells might have bombs.
If you want to guarantee 20 bombs at random locations you could use a temporary array to pick a random from, but remove that randomly selected item so it won't be selected on the next iteration.
Here's a snippet to illustrate the idea:
// make a new array that will hold references to the original cells
let selection = grid.map(cell => cell);
// for the bomb amount...
for(let i = 0 ; i < bombAmount; i++){
// pick a random index
let randomIndex = floor(random(selection.length));
// retrieve the cell at that index and remove it from the selection list
let cell = selection.splice(randomIndex, 1);
// set that cell as a bomb
cell.isBomb = true
}

Joining intersecting paths in illustrator

Short term problem: I have three paths on an artboard. The end of one path has a point at the same position as the beginning of another. The other path is separate. They are all grouped. I have some code that loops through the pathsin the group, and if one path ends where another begins it tried to join them together. The group must be highlighted. To start with my artboard look like this (The top line is two paths):
An after the script is run it looks like this:
With a lot of points added to the end of the line underneath. Could someone lend me a hand with this, Ideally, I'd like it to look like this:
The code looks like this:
var doc = activeDocument;//Gets the active document
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var intersections = true
var group = doc.selection[0]
var paths = []
var intersecttions = 0
// Builds an array of all the paths in the grouped object
if (group !== undefined && group.pageItems.length >= 2) {
for (var i = 0; i < group.pageItems.length; i++) {
var item = group.pageItems[i];
if (item instanceof PathItem) {
item.id = 'Path No' + i;
paths.push(item)
}
}
}
//Sets the first path that will be added to
$.write('paths length ', paths.length,'\n')
var chain = paths[0]
var chainPoints = chain.pathPoints
var chainLength = chainPoints.length - 1
var c1 = chainPoints[0]
var c2 = chainPoints[chainLength]
$.write('c ', c1.anchor,':::', c2.anchor,'\n')
//loops through the paths in the group to see if any overlap the first past
for (var i = 1; i < paths.length-1; i++) {
var link = paths[i]
$.write(link, '\n')
var linkPoints = link.pathPoints
var linkLength = linkPoints.length - 1
$.write('l ', l1.anchor, ':::', l2.anchor, '\n')
if (toString(c1.anchor) === toString(l2.anchor)) {
$.write('inttersection', '\n')
$.write('link', link.id, '\n')
for (var j = 0; j < linkLength; ++j) {
chain.pathPoints.add(linkPoints[j])
$.write (linkPoints[j], '\n')
}
}
}
The first problem is that it's not detecting the instance of overlap correctly. The line:
if (toString(c1.anchor) === toString(l2.anchor)) {
is not comparing one string to another but comparing a true response with another true response. It should be:
if (String(c1.anchor) === String(l2.anchor)) {
you also have to pass across the attributes of each point you are adding to the line and remove the old line, so within the j loop you'll need to add the following
for (var j = 0; j < linkLength; ++j) {
var pp1 = chainPoints.add()
var p2i = linkPoints[j];
pp1.anchor = p2i.anchor;
pp1.rightDirection = p2i.rightDirection;
pp1.leftDirection = p2i.leftDirection;
pp1.pointType = p2i.pointType;
pp1.handle = p2i.handle;
}
link.remove();
This seems to work except that it doesn't add the last point of the second line. I'm guessing that the loop length may not be set correctly If I work it out I'll update the post. I found this in Hiroyuki Sato code for his JoinReasonable scripts http://shspage.com/aijs/en/

Matrix conversion in a particular cluster Structure

I am trying to convert the Distance Matrix I got after calculating Euclidean Distance and taking Matrix form of it, to a manual defined clustered pattern.
In my case, this is the matrix suppose which normal pattern
Suppose, this is the desired cluster order, I have to convert i.e. from 1 2 3 4 to 3 1 2 4, I want to have something like this. I do not want to do it manually since my matrix size is 40 X 40.
It is not clicking to my mind, I can code but algorithm is not coming to my mind. If you could help or someone has done something like this before. Please help me out with it.
I tried reading the data from csv with the help of d3.csv which gives the desired result of 1234 like this :
d3.csv("final.csv", function(loadeddata) {
mydata = loadeddata.map(function(d) {return [+d["1"], +d["2"] , +d["3"], +d["4"]] ;});
to
d3.csv("final.csv", function(loadeddata) {
mydata = loadeddata.map(function(d) {return [+d["3"], +d["1"] , +d["2"], +d["4"]] ;});
so that I can get the matrix in desired clustered format but it did not work coz it shifting whole column to the desired place but not shifting the element wise.
Here is another try I made
var iMax = 4;
var jMax = 4;
var newdata = new Array();
for (i=0;i<iMax;i++) {
newdata[i]=new Array();
for (j=0;j<jMax;j++) {
newdata[i][j]=0;
}
}
var arraycomb = [3,1,2,4];
for ( i = 0; i < 4; i++) {
for ( j = 0; j < 4; j++) {
newdata[arraycomb[i]][arraycomb[j]] = mydata[i][j];
}
}

jquery flot chart highlight dot when near point

I am making a chart using jQuery flot (plot)
https://jsfiddle.net/5gtqwkjg/2/
var updateLegendTimeout = null;
var latestPosition = null;
function updateLegend() {
updateLegendTimeout = null;
var pos = latestPosition;
var axes = plot.getAxes();
if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max || pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
return;
}
/*
var o = plot.pointOffset({ x: pos.x, y: -1.25 });
var ctx = plot.getCanvas().getContext("2d");
ctx.beginPath();
ctx.moveTo(o.left, o.top);
o.top = 0;
ctx.lineTo(o.left, o.top);
ctx.stroke();
*/
var i, j, dataset = plot.getData();
var halfDist = (dataset[0].data[1][0] - dataset[0].data[0][0]) / 2;
for (i = 0; i < dataset.length; ++i) {
var series = dataset[i];
// Find the nearest points, x-wise
for (j = 0; j < series.data.length; ++j) {
if (series.data[j][0] - halfDist > pos.x) {
break;
}
}
// Now Interpolate
var y,
p1 = series.data[j - 1],
p2 = series.data[j];
if (p1 == null) y = p2[1];
else if (p2 == null) y = p1[1];
else y = p1[1];
legends.eq(i).text(series.label.replace(/=.*/, "= " + y.toFixed(2)));
//dataset[i].highlightColor = "#abcdef";
//plot.highlight(dataset[0].series, dataset[0].datapoint);
}
}
$("#placeholder").bind("plothover", function (event, pos, item) {
latestPosition = pos;
if (!updateLegendTimeout) {
updateLegendTimeout = setTimeout(updateLegend, 50);
}
});
I want to add in a functionality that when the user moves the mouse along the x-axis the dot will highlight to indicate what point they are hovering nearest to. I already have the legend reflect the values but how would I highlight the dots?
EDIT: Very helpful answers guys! Here is the finished result if anyone is interested
https://jsfiddle.net/5gtqwkjg/4/
You can make use of the highlight and unhighlight functions provided by Flot.
highlight(series, datapoint)
Highlight a specific datapoint in the data series. You can either
specify the actual objects, e.g. if you got them from a "plotclick"
event, or you can specify the indices, e.g. highlight(1, 3) to
highlight the fourth point in the second series (remember, zero-based
indexing).
unhighlight(series, datapoint) or unhighlight()
Remove the highlighting of the point, same parameters as highlight.
If you call unhighlight with no parameters, e.g. as
plot.unhighlight(), all current highlights are removed.
See https://github.com/flot/flot/blob/master/API.md#plot-methods for reference.
Applying that logic to your question, I think I managed to create the desired result you were looking for.
I first start by unhighlighting everything, just to make sure nothing slips past us when we do highlight points.
for (i = 0; i < dataset.length; ++i) {
plot.unhighlight(); // Unhighlight everything!
var series = dataset[i];
Next up we go do the fun part, highlight all the points! (Just the ones we actually want to highlight)
In your "Find the nearest points, x-wise" loop I added another loop!
for (j = 0; j < series.data.length; ++j) {
if (series.data[j][0] - halfDist > pos.x) {
for(a = 0; a < dataset.length; a++) { // <-- The added loop
// You might want to optimize the way this is done
// The way you were storing the series data didn't seem to work like I..
// ..wanted it do, so I had to iterate the dataset variable again.
// The yellow line won't highlight if you change dataset[a] to series.
plot.highlight(dataset[a], series.data[j][0]);
}
break;
}
}
The result https://jsfiddle.net/qj3068zn/6/, for ease of use.
Do note, none of this is optimized. You're probably better off restructuring your code to provide a more general way to approach this and increase reusability and readability.
Using the highlight() function like Michel de Nijs in his answer, but a simpler version:
1) Put the plot.unhighlight(); at the start of your updateLegend function (you might also want to rename that since it not longer only updates the legend).
2) Add plot.highlight(i, j-1); after your for (j ...) loop.
See this fiddle for the code.

Applying Standard average colors to background gradients

Hey guys I'm having an issue that hopefully someone can help me with,
I have a JSFiddle here of applying the averaged colors to new div block,
so I know it is working, I am having trouble applying them to gradient backgrounds though, and I think I have something seriously messed up, here is the repo
the issue is definetly in this portion of code somehow, I recommend cloning it out for review
var isWebkit = 'webkitRequestAnimationFrame' in window;
var values = $.makeArray($('.value'));
for(var i = 0; i < sigma; i++)
{
var newColor = [
Math.floor(minColor[0]+maxIncrements[0]*i),
Math.floor(minColor[1]+maxIncrements[1]*i),
Math.floor(minColor[2]+maxIncrements[2]*i)
];
var hex = this.toHex(newColor[0], newColor[1], newColor[2]);
(isWebkit) ? $(values[i]).css('background', '-webkit-gradient(linear, left top, left bottom, from(#'+hex+'), to(#000));')
: $(values[i]).css('background', '-moz-linear-gradient(top, #'+hex+', #000);');
}
for(var i = 1; i < sigma+1; i++)
{
var newColor = [
Math.min(255,Math.floor(maxColor[0]+minIncrements[0]*i)),
Math.min(255,Math.floor(maxColor[1]+minIncrements[1]*i)),
Math.min(255,Math.floor(maxColor[2]+minIncrements[2]*i))
];
var hex = this.toHex(newColor[0], newColor[1], newColor[2]);
var c = (sigma+i);
if (c <= values.length) // prevent overlap if we have an odd sigma
{
(isWebkit) ? $(values[c]).css('background', '-webkit-gradient(linear, left top, left bottom, from(#'+hex+'), to(#000));')
: $(values[c]).css('background', '-moz-linear-gradient(top, #'+hex+', #000);');
}
}
EDIT
it looks like in my version compared to my fiddle I am NOT iterating, and always end up with a single hex of 000000 ???
The issue was that it was trying to parse a HASH when hashes weren't accounted for
The fix
/** hex parsers */
(
function(a)
{
a["toRGB"] = function(a)
{
var b = parseInt(a.replace('#', ''), 16); //drop our hash if it exists
return[b>>16,b>>8&255,b&255]
};
a["toHex"] = function(a,b,c)
{
return'#'+(c|b<<8|a<<16|1<<24).toString(16).slice(1) // re-add our hash
}
})(this);

Categories