I would like to sort a set of colours so that I can display them in the most visually pleasing way. I understand that this is a wide topic and what is deemed as visually pleasing is open to debate, so I have chosen to use the Delta-E algorithm. I am using a JS library called Delta-E.
I can use this algorithm to compare two colours at a time and find the perceived difference between them and it is trivial to run through all colour combinations and store this difference for each combination.
However I am unsure how to proceed beyond this point. Once I have deltas for each pair of colours how do I use these values to order the colours?
What kind of sort do I need to use?
I'm actually dealing with the same problem right now. One solution I am tinkering with is to set an anchor color. What I mean by that is that you'd call your deltaE function with the same anchor color and then the color you wish to compare, which will return the difference values from the same color. You can then use that difference value in your Array.sort() call:
const colors = ['#333333', '#f1f1f1', '#00aacc', '#ff6666', '#000000'];
const anchorColor = '#fff'; // White or black might be a decent choice of anchor color
colors.sort((colorA, colorB) => {
// For each color, determine the color difference FROM the anchor color (not each other)
const colorADelta = deltaE(anchorColor, colorA);
const colorBDelta = deltaE(anchorColor, colorB);
if (colorADelta > colorBDelta) {
return 1;
}
if (colorADelta < colorBDelta) {
return -1;
}
return 0;
});
However, in my personal testing, I've found that the deltaE difference values weren't exactly right for this anchor technique, and I instead used the Euclidean distance as the value, from this library (which also has a Delta-E function).
Related
I have a data structure like:
{
id: X
subId: Y
}
The id should decide what kind of color (greenish, blueish, redish, yellowish) it should be. d3.scale.category10() should be enough.
From this color I would like to have 'subcolors' (different blues, different greens) for every subId (the more different they look, the better - however, seeing the difference between id's is more important than seeing the difference between subIds).
How would I solve this problem?
You can use D3's .brighter() and/or .darker() functions to modify the colours you get from the scale for the categories. Note that both functions take an argument that allows you to control how much brighter/darker the colours get (values less than 1).
By using the simple array app.selection[x], you can apply a transformation to any object in the selection, independently. But how do I apply a transformation to the entire selection together?
For example: inside InDesign, I can select two side-by-side objects and flip them horizontally, causing them to switch places and flip.
Inside a script, I can target each object in the selection, but they will not switch places; they will remain in the same place and flip.
for ( var x = 0; x < app.selection.length; x++ ){
app.selection[x].absoluteFlip = Flip.HORIZONTAL;
}
I could possibly group the selection, apply a transformation, then ungroup when finished, but this seems like unnecessary bulk that could slow down the code. I can easily do it manually inside InDesign, so it should follow that there's some way to access app.selection as a single object instead of an array. Does such an object exist?
Not really a solution, but it's worth noting that I don't think absoluteFlip is the action being performed, but a state indicating if the item has ben flipped. It's writable so you can set the state, but I think what's happening when using the menu to flip is flipItem: http://jongware.mit.edu/idcs6js/pc_PageItem.html#flipItem,
in which you can set "around" coordinates.
Now getting the origin of the selection box isn't straightforward for some reason (or maybe it is but I don't know how), but you can either use first object coordinates to set the origin so you can flip it around different coordinates depending on order of selection. Or you can sort the array to find left most coordinates (or whichever is needed), like this:
var selection_array = app.selection;
selection_array.sort(function(a, b){return a.visibleBounds[1]-b.visibleBounds[1]})
var flip_origin = [selection_array[0].visibleBounds[1],selection_array[0].visibleBounds[0]]
for(i=0;i<app.selection.length;i++){
app.selection[i].flipItem(Flip.HORIZONTAL, flip_origin);
}
Not sure it's easier or faster than grouping and ungrouping though.
Consider resize. It has a "individual/global" parameter :
void resize (in: varies, from: varies, by: ResizeMethods, values: Array of varies[, resizeIndividually: bool=true][, consideringRulerUnits: bool=false])
Resize the page item.
Trying to create a random (0/1) boolean operation. I have a multidimensional array set up. So far, everything works. Am I on the right path? I currently use recursion; is there a more efficient way to do this?
function randomMove(){
var cs=b.length,
cr=Math.floor((Math.random()*cs)+1)-1,
cc=Math.floor((Math.random()*cs)+1)-1;
if(b[cr][cc]===""){ // THIS IS DEPENDENT ON EXISTING CODE. VIEW FIDDLE. //
// DO STUFF //
} else { randomMove(); }
}
Is this considered a good way to create a random move for 2 players? Or is recursion the wrong process here?
Fiddle
Select the cells that can possibly be selected, then choose a random one by index.
http://jsfiddle.net/Ehqka/1/
$.fn.random = function(){
return this.eq(Math.floor(Math.random()*this.length));
};
function randomMove(){
$("#board td").not(".o,.comp").random().addClass('comp');
testWin();
}
It selects all cells in the board, drops the ones that have a class of o or comp from the selection, generates a random number between 0 and the number of remaining cells, then selects the cell at that index to add a class to.
Note, however, your method will be "faster" than the above on the first move due to the fact that on the first move, every move is a valid one therefore it will never iterate past the first time. Mine can be slightly optimized to be more efficient on the first by removing the .not(), but your's should still be "faster" because it doesn't have to go to the DOM.
"faster" is relative, my method will grow less efficient as the table grows than yours will on the first move. As more and more moves happen, your method will become less and less efficient since more and more of the possible moves are invalid.
I need help/advice for improving/commenting my current design please :)
This relates to collision detection in a simple game: Dynamic bodies (moving ones) might collide with static bodies (i.e. ground, walls). I'm porting my Obj-C model to Javascript and am facing memory/performance questions as to my way of implementing this.
I'm using a very basic approach: An array of arrays represents my level in terms of physic opacity.
bit set to 0: Transparent area, bodies can go through
bit set to 1: Opaque area, bodies collide
Testing the transparency/opacity of a pixel simply goes as follows:
if (grid[x][y]) {
// collide!
}
My knowledge of JS is pretty limited in termes of performance/memory and can't evaluate how good this approach is :) No idea of the efficiency of using arrays that being said.
Just imagine a 1000-pixel wide level that's 600px high. It's a small level but this already means an array containing 1000 arrays each containing up to 600 entries. Besides, I've not found a way to ensure I create a 1bit-sized element like low-level languages have.
Using the following, can I be sure an entry isn't something "else" than a bit?
grid[x][y] = true;
grid[x][y] = false;
Thanks for your time and comments/advices!
J.
If you have an 1000x600 grid, you can guarantee you have at least 601 arrays in memory (1001 if you do it the other way round).
Rather than doing this, I would consider using either 1 array, or (preferrably) one object with a mapping scheme.
var map = {};
map["1x1"] = 1;
map["1x3"] = 1;
// assume no-hits are empty and free to move through
function canGoIn(x, y) {
return map.hasOwnProperty(x + "x" + y);
};
Alternately;
var map = [];
var width = 600;
map.push(0);
map.push(1);
// etc
function canGoIn(x, y) {
return map[(x * width) + y] == 1;
}
a boolean value won't be stored as just one bit, and that is also true for any other language I know (C included).
If you are having memory issues, you should consider implementing a bitarray like this one: https://github.com/bramstein/bit-array/blob/master/lib/bit-array.js
You will have to make your 2d array into a simple vector and converting your x, y coordinates like this: offset = x + (y * width);
Browsing an array will still lead to a multiplication to evaluate the offset so using a vector is equivalent to arrays.
But I suspect that calling a function (in case your using a bit-array) and doing some evaluations inside will lead to poorer performances.
I don't think you can gain performances and save memory at the same time.
I’m generating multiple, random sized, circular elements using the Raphael JavaScript library but because it’s random a lot of the circular elements being generate overlap or cover each other. What I wanted to know, is there any way with JavaScript to tell if one element is in already in particular position so to avoid the overlapping? Essentially, I want to create random elements on a canvas, of a random size that don’t overlap or cover each other.
There's a couple of test files I created here to give you an idea of what I'm doing. The first one generates random objects and the second link sets them to a grid to stop the overlapping.
http://files.nicklowman.co.uk/movies/raphael_test_01/
http://files.nicklowman.co.uk/movies/raphael_test_03/
The easiest way is to create an object and give it a repulsive force that degrades towards zero at it's edge. As you drop these objects onto the canvas the objects will push away from each other until they reach a point of equilibrium.
Your examples aren't working for me, so I cannot visualize your exact scenario.
Before you "drop" an element on the canvas, you could query the positions of your other elements and do some calculations to check if the new element will overlap.
A very simple example of this concept using circle elements might look like this:
function overlap(circ1, circ2) {
var attrs = ["cx", "cy", "r"];
var c1 = circ1.attr(attrs);
var c2 = circ2.attr(attrs);
var dist = Math.sqrt(Math.pow(c1.cx - c2.cx ,2) + Math.pow(c1.cy - c2.cy, 2));
return (dist < (c1.r + c2.r));
}
var next_drop = paper.circle(x, y, r);
for (var i in circles) {
if (overlap(next_drop, circles[i])) {
// do something
}
}
Of course calculating just where you're going to place a circle after you've determined it overlaps with others is a little more complicated.