I'm trying to do a bubble chart similar to Mike Bostock's:
However, instead of randomly generating the nodes, I want them to be generated for a json. Suppose I have a dataset variable that is a valid JSON how do I generate a nodes variable from this that can be used for the force layout.
Mike's implementation (for randomly-generated circles) is:
var nodes = d3.range(n).map(function() {
var i = Math.floor(Math.random() * m),
v = (i + 1) / m * -Math.log(Math.random());
return {
radius: radius(v),
color: color(i),
cx: x(i),
cy: height / 2
};
});
Let's suppose my dataset JSON is something like:
{"nodes":[{"name": "node_name", "size": 18}, ... ]}
And I want the radius of each circle to be the size of each object in the JSON array.
nodes is an array of objects which each have radius, color, cx and cy attributes. All you need to do is create such an array from your data. How exactly to do this will depend on your data. Note that you don't need to create all the attributes -- if all the nodes can have the same color for example, you don't need to add the corresponding attribute (but also need to change the code that actually sets the color later on).
Related
In the following example, there is a function called generateTexture().
Is it possible to draw text (numbers) into the pixel array? Or is it possible to draw text (numbers) on top of that shader?
Our goal is to draw a circle with a number inside of it.
https://forge.autodesk.com/blog/using-dynamic-texture-inside-custom-shaders
UPDATE:
We noticed that each circle can't use a unique generateTexture(). The generateTexture() result is used by every single one of them. The only thing that can be customized per object is the color, plus what texture is used.
We could create a workaround for this, which is to generate every texture from 0 to 99, and to then have each object choose the correct texture based on the number we want to display. We don't know if this will be efficient enough to work properly though. Otherwise, it might have to be 0 to 9+ or something in that direction. Any guides on our updated question would be really appreciated. Thanks.
I am able to successfully display text with the following code, simply replace generateTexture() by generateCanvasTexture() in the sample and you should get the result below:
const generateCanvasTexture = () => {
const canvas = document.createElement("canvas")
const ctx = canvas.getContext('2d')
ctx.font = '20pt Arial'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(new Date().toLocaleString(),
canvas.width / 2, canvas.height / 2)
const canvasTexture = new THREE.Texture(canvas)
canvasTexture.needsUpdate = true
canvasTexture.flipX = false
canvasTexture.flipY = false
return canvasTexture
}
It is possible but you would need to implement it yourself. Shaders are a pretty low level feature so there is no way to directly draw a number or a text, but you can convert a given character into its representation as a 2d pixel array.
Is there a language which will support the following concept or is there a pattern to achieve something similar with existing one?
Concept
I want to define a Rectangle with the following properties: Length, Height, Area, Perimeter; where Area = Length * Height and Perimeter = (2 * Length) + (2 * Height).
Given the statement above, if I want to create a Rectangle by giving it a Length and a Height, it should of course automatically fill out the rest of the properties.
However, it should go further and automatically allow you to create a Rectangle with any two properties (say Height and Perimeter) because that is also mathematically enough to create the same Rectangle.
Example
To help explain the idea, take this example:
//Declaration
Rectangle
{
Height, Length, Area, Perimeter;
Area = Height * Length;
Perimeter = (2 * Length) + (2 * Height);
}
//Usage
main()
{
var rectangleA = new Rectangle(Height, Length);
var rectangleB = new Rectangle(Height, Area);
Assert(rectangleA == rectangleB);
}
Notice how I didn't need to define constructors for Rectangle. Notice I did not need specify the specific logic needed if a Rectangle was created using Height and Area.
Edit: Should be rectangle and not a square for a proper example.
What you are looking for is a language with an integrated computer algebra system. It has to be able to resolve equations with respect to different variables.
While it would be possible to implement something like this, I doubt that it would make sense because in many cases there will be either no solution or multiple solutions.
Even your simple example will not work if only area and perimeter are given because there will usually be two solutions. (I assume that your class actually represents a rectangle and not a square, otherwise you should not have separate variables for length and height.)
Example:
Input: area = 2, perimeter = 6
Solution 1: length = 2, height = 1
Solution 2: length = 1, height = 2
Another remark not really related to your question: Your class obviously contains redundant member variables. This is a bad thing for various reasons, the most important being the possibility of inconsistencies. Unless you have very strict performance constraints, you should store only two of them, say length and width, and provide methods to calculate the others when needed.
Of course such a language exists. Many do, as you've now pointed out in your own comment to this answer.
In the example below I'll be using the Powerloom representation system, implemented in a language called STELLA.
You can play with it from within a Common Lisp environment.
Once you have everything installed you can load the language by running:
(cl:load "load-powerloom.lisp")
(in-package "STELLA")
(in-dialect "KIF")
That's about all you need to start building awesome geometrical objects.
Within STELLA you may define a concept with the primitive defconcept:
(defconcept Rectangle (?r)
:documentation "Curious geometrical objects that live on a plane.")
And define its properties with deffunction:
(deffunction rect-height ((?t Rectangle)) :-> (?n INTEGER))
(deffunction rect-length ((?t Rectangle)) :-> (?n INTEGER))
(deffunction area ((?t Rectangle)) :-> (?n INTEGER))
(deffunction perimeter ((?t Rectangle)) :-> (?n INTEGER))
To make the relations between area, perimeter and the sides of your rectangle, you'll have to make some assertions. That's what you'll have assert for.
(assert (forall (?t Rectangle)
(= (area ?t) (* (rect-height ?t) (rect-length ?t)))))
(assert (forall (?t Rectangle)
(= (perimeter ?t) (+ (* 2 (rect-height ?t))
(* 2 (rect-length ?t))))))
You are telling STELLA that for all rectangles, the area is the product of height and length, and that for all rectangles, the perimeter is twice the height plus twice the length.
Now you can instantiate your objects, and it doesn't matter what properties you give it, as long as they make sense.
(definstance rect1 :Rectangle true :rect-height 10 :rect-length 10)
(definstance rect2 :Rectangle true :area 40 :rect-height 20)
Here you instantiate rect1 with height and length as parameters, and rect2 with area and height.
But its always good to check that the language is doing what you expect:
STELLA> (retrieve all ?x (= (area rect1) ?x))
There is 1 solution:
#1: ?X=100
STELLA> (retrieve all ?x (= (rect-length rect2) ?x))
There is 1 solution:
#1: ?X=2
If you ever get tired of rectangles and decide to build a beautiful square, why not derive a concept?
(defconcept Square ((?r Rectangle))
:documentation "Weird rectangles that fascinated the Greeks"
:<=> (= (rect-height ?r) (rect-length ?r)))
Simply tell STELLA that squares are rectangles where height and length are equal.
Now try it out:
STELLA> (definstance nice-rectangle :Rectangle true :rect-length 10 :area 100)
|i|NICE-RECTANGLE
STELLA> (ask (Square nice-rectangle))
TRUE
I'm not an expert at all, but I find the language fascinating. It's sad that there is so little information about it on the internet. Even the manual is incomplete.
For more information I'd suggest starting with these slides.
The famous book SICP teaches how to build a nondeterministic evaluator for such a language here.
And finally, a wonderful write up describing motivations and applications behind these ideas can be seen here.
In C#, you can use properties, which have implicit getters and setters. That way you can write something like:
public class Square {
public int Length {
get { return length; }
set { length = value; }
}
public int Area {
get { return length * length; }
set { length = Math.Sqrt(value); }
}
public int Perimeter {
get { return length * 4; }
set { length = value / 4; }
}
private int length;
}
Now you can write:
Square square = new Square();
square.Length = 2;
Console.WriteLine(square.Length); // "2"
Console.WriteLine(square.Area); // "4"
Console.WriteLine(square.Perimeter); // "8"
square.Area = 9;
Console.WriteLine(square.Length); // "3"
Console.WriteLine(square.Area); // "9"
Console.WriteLine(square.Perimeter); // "12"
Edit:
C# also allows you name properties at your choosing when instantiating an object:
Square square1 = new Square { Perimeter = 12 };
Square square2 = new Square { Length = 4 };
I don't think something like this does exist in the form of a programming language.
Ontology
However the first approach I can think about is defining an Ontology, I mean a set of rules about
Entities: Rectangle, Square, Dog, Car, etc...
Attributes: Area, Height, Number of Wheels, etc...
Relations between (1) and (2): Rectangle's Area is Height * Width, ...
Now given a list of attributes and the required output Entity
I have height and width and I need a Rectangle
the system could search for a path through the rules graph to produce the required outcome based on the provided inputs.
Real world example
Wolfram Alpha probably follows the technique described above
I'm trying to to do some dynamic MovieClips placement here. I've been trying for a couple'o days and I can't find the right way to do the trick. It's the continuation for this. I didn't manage to properly make my MC's appear in the triangle, so I've made a pyramid of rectangles (suits my case better, beacuse I can change each of'em, to better fit my desired shape - a not-so-regular triangle).
Here's the code with some comments:
import flash.events.MouseEvent;
import flash.display.MovieClip;
btn_toys_2.confirm.addEventListener(MouseEvent.MOUSE_UP, confirmToys);
var toysPlc:Array = new Array(); //an array for a bunch of rectangles
var toAdd:int = 100 //this is supposed to be dynamic, user defined
var toy:MovieClip = new shar_001; //an MC from a library
for (var j:int=0; j<33; j++){
toysPlc.push("tPl_" + j); //here I add that bunch of rects into an array
}
function confirmToys(e:MouseEvent):void{
for (var k:int=0; k<toAdd; k++){ //supposed to add an "toAdd" amount of "toys"
var p:int = Math.random()*toysPlc.length; //^do so in a random rect
toysPlc[p].addChild(toy); //supposed to place a toy in a random rect
toy.x = Math.random()*toysPlc[p].width; //positioning
toy.y = Math.random()*toysPlc[p].height; //positioning
}
}
The error I get is: TypeError: Error #1006: value is not a function.
What I DID manage is to place a single toy in a random of these rects, tho I don't remember how :)
Thanks in advance!
EDIT: null asked me to clarify the case, so here's the whole picture:
I've got:
- triangle-like MC (since a triangle MC is a rectangle for flash anyway, I've solved this by creating a pyramid of 33 rectangles, layered on each other);
- toys (multiple frames to change whenever I need to);
- text field (to input the quantity of desired toys);
- confirm button (to make the magic happen once clicked);
Now I need a user to input a 3-digit number in the input field, press "confirm", and 0.4 of that quantity is supposed to appear in the "triangle-like MC".
For example: user inputs a number: 600, the end value is 600*0.4=240. Now 240 "toys" are randomly spreaded between my 33 rectangles, within their width (which is different for every single one).
Hope that explains a bit more.
A simplified sample of what I need here.
Is there a way to fill an array with MovieClips rather than String values? That would be THE answer to this question here.
There is in fact more than one way:
Place all the instance names into the Array when you create it:
var rectangles:Array = [instanceName1, instanceName2];
there are no quotation marks, which create string literals. Just the names.
This approach quickly becomes impractical for large numbers of objects.
Given that the instance names have a number component, iterate through the names in conjunction with getChildByName(). I assume that this is what you were trying with in your question:
var rectangles:Array = []; // initialise empty array
for (var j:int=0; j<33; j++){
rectangles.push(getChildByName("tPl_" + j));
}
original answer
toysPlc.push("tPl_" + j); //here I add that bunch of rects into an array
No you don't. You are filling the Array with String objects. It's totally unrelated to any rectangle whatsoever.
Now this next line, tries to call a function on each String, which fails.
toysPlc[p].addChild(toy);
The above is equivalent to
"tPl_0".addChild(toy);
"tPl_1".addChild(toy);
// etc.
A String doesn't have that method addChild.
I have two questions that are related. I am trying to make a rectangular grid based on my csv dataset, where each rectangle represents a data point. Eventually, I went to set the opacity of each cell based on the min/max scale for that column.
My first attempt was to create rows per d elements. I found some code to do this:
for (var n = 0; n < data.length; n++ ) {
// create each set of rows
var rows = svg.selectAll('rect' + ' .row-' + (n + 1))
.data(d3.range(headers.length))
.enter().append('rect')
.attr({
class: function(d, i) {
return 'col-' + (i + 1);
},
id: function(d, i) {
return 's-' + (n + 1) + (i + 1);
},
width: square,
height: square,
x: function(d, i) {
return i * square;
},
y: n * square,
fill: 'red'
})
I'm not fully understanding how this works. It creates n rows based on the number of rows in my csv. But now I can't move forward because I don't know how to set the opacity. I want to create an anonymous function on the fill attribute, but I don't know how to access what column of the CSV I'm in. If I access i, it would be what row I'm in, and if I access d then it is undefined.
My next thought was to instead, just each column to set of rectangles. Is there a way I can access just that column. So:
var column1 = data[Column1];
var column1Scale = .domain([d3.min(data, function(d) { return d["Column1"]}),
d3.max(data, function(d) { return d["Column1"]})])
var column1rects = svg.select("body").data(column1).enter().append("rect")...
I can then set the x to be the same for each rectangle and use an anonymous function with y, and then call the scale on the opacity.
But, I don't know how to access just that column, or do I just reference in by name like I did in the scale function? And lastly, am I going about building a grid all wrong?
I also sometimes still struggle with the D3 data join. Some may find Mike Bostock's Thinking with Joins page useful.
What helps me is to imagine a D3 selection of DOM elements as an array which can be associated with an array of data entries. This association happens whenever you say .data(yourData) on a D3 selection.
After that, you can let D3 take care of creating "missing" DOM elements via the .enter() selection. That means for all the elements that exist in yourData but not yet in the DOM, you can do something like .append(yourNewElement).
In your case, the data set is 2-dimensional: The CSV is basically an array of rows and each row is an array of data entries. That means you need two places where you join the respective arrays to some DOM elements:
Each data row can be associated with a group of grid cells
and each one of these groups can be associated with the elements of its row.
Based on your code, I came up with the following example which lets you address each grid cell individually:
var svg = d3.select('body').append('svg');
var square = 20,
data = [
[1,2,3],
[4,5,6],
[7,8,9]
];
var rows = svg.selectAll('g') // Select all 'g' (SVG group) elements
.data(data), // and associate each one with a data row.
newRows = rows.enter(); // Create the "enter selection", i.e. all
// data rows that don't exist yet as 'g' elements.
newRows.append('g') // Create 'g' elements for each row
.attr('transform', function(row_d, row_i) {
// The new group is translated vertically dependent on the row_i
return 'translate(0,' + (row_i * square) + ')'
});
// Now that all rows are created, let's create the rectangles in each row:
rows.each(function(row_d, row_i) {
var row = d3.select(this), // Select 'this', which refers to the 'g'
// element of the current row.
cells = row.selectAll('rect') // Select all 'rect' elements in this row
.data(row_d), // and associate each one with a data entry.
newCells = cells.enter(); // Create the "enter selection", i.e. all
// data entries that don't exist yet as 'rect' elements.
// Create 'rect' elements for each new entry:
newCells.append('rect').attr({
y: 0, // The enclosing 'g' elements take care of the y axis,
x: function(cell_d, cell_i) { // so we only need to set x dependent on cell_i,
return cell_i * square; // which is the index of the cell within the row.
},
width: square,
height: square,
fill: function(cell_d, cell_i) {
// here we can do anything with the current cell data cell_d
return d3.rgb(cell_d*25,cell_d*25,cell_d*25);
// or with cell_i, which is effectively the column index:
//return d3.rgb(cell_i*100,cell_i*100,cell_i*100);
}
});
});
I have a 2D tilemap that is generated in chunks consisting of 2x2 cells each. I can reference the chunk itself and get the index of each particular cell within the chunk. However, I'd like to also store the index of the first tile within that chunk, which is not automatically generated.
For example, clicking on the highlighted chunk would always produce "0", clicking on the next one would produce "2", and clicking on the one under it would always produce "20". Red numbers indicate the tile/cell's index. The yellow outline demonstrates an actual chunk.
Within the confines of the chunk, what is the best way to get 0, 2, 4, 6, 8, 20, and so on?
The code that generates this is in Actionscript 3, and is a basic dual for loop.
EDIT:
I thought about it for a moment and decided to add in my index search code. I'm not entirely sure if this will help, especially since it is for finding individual cell index and not a particular index location in chunks.
public function mousePosistion():Number
{
var mouseColX: Number = 0;
var mouseColY: Number = 0;
mouseColY = Math.ceil(this.mouseY / 64);
mouseColX = Math.ceil(this.mouseX / 64);
var mouseIndex:Number = mouseColX + (20 * mouseColY);
return mouseIndex;
}
Note: It's formatted for the actual map which is at 20 width, not 10 as in the example.
Off the top of my head, just by looking at the image you have you could go:
[in pseudocode]
if tileIndex tens digit is odd, minus 10
if tileIndex ones digit is odd, minus 1
I figured it out after a little time. Using the dual For loop, the index calculation came out to this: baseIndex = (X * 2) + (Y * 20); Matches each index on the basic tiles perfectly. 2 is the size of the super, 20 is the width of the map doubled. To expand this into a variable based solution:
baseIndex = (X * chunkSize) + (Y * (mapSize * 2));