Pattern Repeat on object in KonvaJS - konvajs

Is there any way to repeat a pattern in KonvaJS through a user input? I have this (DEMO). However,I am having difficulties wrapping my head around this next step. Is it possible?
Edit: I would like to programmatically clone/repeat the arc's peaks per span based on the user input and tile it along the x axis.

You can just do this:
const lines = [];
for (var i = 0; i < numArchPeaks; i++) {
const single = [0, 0, 90, -50, 180, 0];
const perSpan = single.map((x) => x / numArchPeaks);
lines.push(
<Line x={x + i * 180 / numArchPeaks} y={y} points={perSpan} tension={1} stroke="black" />
);
}
// then in render:
<Layer>{lines}</Layer>
https://codesandbox.io/s/stupefied-fermi-vz9z7?file=/src/KonvaExample.js

Related

Scaling points of line - konvajs

I'm looking to have a transform on a KonvaJS line. I have all of it working and it scales the object, however I'd like it to adjust the points of the line instead of setting the scale property when I grab a resize handle. Would also consider doing this in a path as well.
So the goal is that my objects scaleX and scaleY is always 1 and it's just the points that are scaling out.
Is this at all possible?
You just need to apply the scale to points property:
shape.on('transformend', () => {
const oldPoints = shape.points();
const newPoints = [];
for(var i = 0; i< oldPoints.length / 2; i++) {
const point = {
x: oldPoints[i * 2] * shape.scaleX(),
y: oldPoints[i * 2 + 1] * shape.scaleY(),
}
newPoints.push(point.x, point.y);
}
shape.points(newPoints);
shape.scaleX(1);
shape.scaleY(1);
layer.draw();
})
Demo: https://jsbin.com/vuhakuvoxa/1/edit?html,js,output

How to add line which runs through origin (from positive to negative) on a scatterplot - highchart

I am trying to create a reference line that runs through the origin and passes from negative to positive. See an example of what i am trying to achieve - see the threshold line. This threshold line must run through all three x, y coordinates (-1,-45,000), (0.0), (1, 45,000).
enter image description here
Below is my work so far.
http://jsfiddle.net/catio6/rhf6yre5/1/
I've looked at this for reference but have had had no luck after several hours of attempts of replicating this with all three x, y coordinates (-1,-45,000), (0.0), (1, 45,000): http://jsfiddle.net/phpdeveloperrahul/XvjfL/
$(function () {
$('#container').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar']
},
series: [{
data: [29.9, 71.5, 256]
}]
}, function(chart) { // on complete
console.log("chart = ");
console.log(chart);
//chart.renderer.path(['M', 0, 0, 'L', 100, 100, 200, 50, 300, 100])
chart.renderer.path(['M', 75, 223.5,'L', 259, 47])//M 75 223.5 L 593 223.5
.attr({
'stroke-width': 2,
stroke: 'red'
})
.add();
});
});
So Highcharts doesn't have, as far as I know, a way to define a line that goes from/to infinity.
One idea I had to solve this issue for you is dynamically calculate the values for the line series based on your data. The idea is simple: Given the maximum values for X and Y you want to plot, we just need to limit the axis to a certain value that makes sense and calculate the values for the asymptote series in order to make it seems infinite. My algorithm looks like this:
// Get all your other data in a well formated way
let yourData = [
{x: 0.57, y: 72484},
{x: 0.57, y: 10000}
];
// Find which are the maximum x and y values
let maxX = yourData.reduce((max, v) => max > v.x ? max : v.x, -999999999);
let maxY = yourData.reduce((max, v) => max > v.y ? max : v.y, -999999999);
// Now you will limit you X and Y axis to a value that makes sense due the maximum values
// Here I will limit it to 10K above or lower on Y and 2 above or lower on X
let maxXAxis = maxX + 2;
let minXAxis = - (maxX + 2);
let maxYAxis = maxY + 10000;
let minYAxis = -(maxY + 10000);
// Now you need to calculate the values for the Willingness to pay series
let fn = (x) => 45000 * x; // This is the function that defines the Willingness to pay line
// Calculate the series values
let willingnessSeries = [];
for(let i = Math.floor(minXAxis); i <= Math.ceil(maxXAxis); i++) {
willingnessSeries.push([i, fn(i)]);
}
Here is a working fiddle: http://jsfiddle.net/n5xg1970/
I tested with several values for your data and all of them seem to be working ok.
Hope it helps
Regards

How to detect Dynamic Obstacles in point clouds

I want to implement stereo vision in a robot. I have calculated disparity map and point clouds. now I want to detect Dynamic Obstacles in scene.
Can anyone help me please?
Best Regards
Here is how I do that for 2d navigation.
First prepare two 2d elevation maps as 2d arrays. Set elements of one of the arrays to min height of points projected to the same cell of the 2d map, and set elements of the other array to max heights like this:
static const float c_neg_inf = -9999;
static const float c_inf = 9999;
int map_pixels_in_m_ = 40; //: for map cell size 2.5 x 2.5 cm
int map_width = 16 * map_pixels_in_m_;
int map_height = 16 * map_pixels_in_m_;
cv::Mat top_view_min_elevation(cv::Size(map_width, map_height), CV_32FC1, cv::Scalar(c_inf));
cv::Mat top_view_max_elevation(cv::Size(map_width, map_height), CV_32FC1, cv::Scalar(c_neg_inf));
//: prepare elevation maps:
for (int i = 0, v = 0; v < height; ++v) {
for (int u = 0; u < width; ++u, ++i) {
if (!pcl::isFinite(point_cloud_->points[i]))
continue;
pcl::Vector3fMap point_in_laser_frame = point_cloud_->points[i].getVector3fMap();
float z = point_in_laser_frame(2);
int map_x = map_width / 2 - point_in_laser_frame(1) * map_pixels_in_m_;
int map_y = map_height - point_in_laser_frame(0) * map_pixels_in_m_;
if (map_x >= 0 && map_x < map_width && map_y >= 0 && map_y < map_width) {
//: update elevation maps:
top_view_min_elevation.at<float>(map_x, map_y) = std::min(top_view_min_elevation.at<float>(map_x, map_y), z);
top_view_max_elevation.at<float>(map_x, map_y) = std::max(top_view_max_elevation.at<float>(map_x, map_y), z);
}
}
}
Then
//: merge values in neighboring pixels of the elevation maps:
top_view_min_elevation = cv::min(top_view_min_elevation, CvUtils::hscroll(top_view_min_elevation, -1, c_inf));
top_view_max_elevation = cv::max(top_view_max_elevation, CvUtils::hscroll(top_view_max_elevation, -1, c_neg_inf));
top_view_min_elevation = cv::min(top_view_min_elevation, CvUtils::hscroll(top_view_min_elevation, 1, c_inf));
top_view_max_elevation = cv::max(top_view_max_elevation, CvUtils::hscroll(top_view_max_elevation, 1, c_neg_inf));
top_view_min_elevation = cv::min(top_view_min_elevation, CvUtils::vscroll(top_view_min_elevation, -1, c_inf));
top_view_max_elevation = cv::max(top_view_max_elevation, CvUtils::vscroll(top_view_max_elevation, -1, c_neg_inf));
top_view_min_elevation = cv::min(top_view_min_elevation, CvUtils::vscroll(top_view_min_elevation, 1, c_inf));
top_view_max_elevation = cv::max(top_view_max_elevation, CvUtils::vscroll(top_view_max_elevation, 1, c_neg_inf));
Here CvUtils::hscroll and CvUtils::vscroll are functions that 'scroll' the content of a 2d array filling the elements on the edge that got no value in the scroll with the value of the third parameter.
Now you can make a difference between the arrays (taking care about elements with c_inf and c_neg_inf values) like this:
//: produce the top_view_elevation_diff_:
cv::Mat top_view_elevation_diff = top_view_max_elevation - top_view_min_elevation;
cv::threshold(top_view_elevation_diff, top_view_elevation_diff, c_inf, 0, cv::THRESH_TOZERO_INV);
Now all non-zero elements of top_view_elevation_diff are your potential obstacles. You can enumerate them and report 2d coordinates of those of them that are grater then some value as your 2d obstacles.
If you can wait till the middle of September, I'll put into a public repository full code of a ROS node that takes a depth image and depth camera info and generates a faked LaserScan message with measurements set to distance to found obstacles.

(MATH ISSUE) Creating a SPIRAL out of points: How do I change "relative" position to absolute position

Recently I had the idea to make a pendulum out of points using Processing, and with a little learning I solved it easily:
int contador = 0;
int curvatura = 2;
float pendulo;
void setup(){
size(300,300);
}
void draw(){
background(100);
contador = (contador + 1) % 360; //"CONTADOR" GOES FROM 0 TO 359
pendulo = sin(radians(contador))*curvatura; //"PENDULO" EQUALS THE SIN OF CONTADOR, SO IT GOES FROM 1 TO -1 REPEATEDLY, THEN IS MULTIPLIED TO EMPHASIZE OR REDUCE THE CURVATURE OF THE LINE.
tallo(width/2,height/3);
println(pendulo);
}
void tallo (int x, int y){ //THE FUNTION TO DRAW THE DOTTED LINE
pushMatrix();
translate(x,y);
float _y = 0.0;
for(int i = 0; i < 25; i++){ //CREATES THE POINTS SEQUENCE.
ellipse(0,0,5,5);
_y+=5;
rotate(radians(pendulo)); //ROTATE THEM ON EACH ITERATION, THIS MAKES THE SPIRAL.
}
popMatrix();
}
So, in a brief, what I did was a function that changed every point position with the rotate fuction, and then I just had to draw the ellipses in the origin coordinates as that is the real thing that changes position and creates the pendulum ilussion.
[capture example, I just need 2 more points if you are so gentile :)]
[capture example]
[capture example]
Everything was OK that far. The problem appeared when I tried to replace the ellipses for a path made of vertices. The problem is obvious: the path is never (visually) made because all vertices would be 0,0 as they move along with the zero coordinates.
So, in order to make the path possible, I need the absolute values for each vertex; and there's the question: How do I get them?
What I know I have to do is to remove the transform functions, create the variables for the X and Y position and update them inside the for, but then what? That's why I cleared this is a maths issue, which operation I have to add in the X and Y variables in order to make the path and its curvature possible?
void tallo (int x, int y){
pushMatrix();
translate(x,y);
//NOW WE START WITH THE CHANGES. LET'S DECLARE THE VARIABLES FOR THE COORDINATES
float _x = 0.0;
float _y = 0.0;
beginShape();
for(int i = 0; i < 25; i++){ //CREATES THE DOTS.
vertex(_x,_y); //CHANGING TO VERTICES AND CALLING THE NEW VARIABLES, OK.
//rotate(radians(pendulo)); <--- HERE IS MY PROBLEM. HOW DO I CONVERT THIS INTO X AND Y COORDINATES?
//_x = _x + ????;
_y = _y + 5 /* + ???? */;
}
endShape();
popMatrix();
}
We need to have in mind that pendulo's x and y values changes in each iteration of the for, it doesn't has to add the same quantity each time. The addition must be progressive. Otherwise, we would see a straight line rotating instead of a curve accentuating its curvature (if you increase curvatura's value to a number greater than 20, you will notice the spiral)
So, rotating the coordinates was a great solution to it, now it's kind of a muddle to think the mathematical solution to the x and y coordinates for the spiral, my secondary's knowledges aren't enough. I know I have to create another variable inside the for in order to do this progression, but what operation should it have?
I would be really glad to know, maths
You could use simple trigonometry. You know the angle and the hypotenuse, so you use cos to get the relative x position, and sin to the y. The position would be relative to the central point.
But before i explain in detail and draw some explanations, let me propose another solution: PVectors
void setup() {
size(400,400);
frameRate(60);
center = new PVector(width/2, height/3); //defined here because width and height only are set after size()
}
void draw() {
background(255);
fill(0);
stroke(0);
angle = arc_magn*sin( (float) frameCount/60 );
draw_pendulum( center );
}
PVector center;
float angle = 0;
float arc_magn = HALF_PI;
float wire_length = 150;
float rotation_angle = PI/20 /60 ; //we divide it by 60 so the first part is the rotation in one second
void draw_pendulum(PVector origin){
PVector temp_vect = PVector.fromAngle( angle + HALF_PI);
temp_vect.setMag(wire_length);
PVector final_pos = new PVector(origin.x+temp_vect.x, origin.y+temp_vect.y );
ellipse( final_pos.x, final_pos.y, 40, 40);
line(origin.x, origin.y, final_pos.x, final_pos.y);
}
You use PVector class static method fromAngle( float angle ) that returns a unity vector of the given angle, then use .setMag() to define it's length.
Those PVector methods will take care of the trigonometry for you.
If you still want to know the math behind it, i can make another example.

AS2: Tween around ellipse

I have 7 movieclips on stage I want to tween around an ellipse from different start points. I am having lots of trouble doing this.... I used a circle formula at first and then divided the y value by the width of the ellipse over the height. This sort of worked but after every rotation the y value was a little of. That code is:
this._x += (Math.cos(angle * Math.PI/180) * radius);
this._y += (Math.sin(angle * Math.PI/180) *radius)/1.54;
I also have trouble finding the angle of the start point, if it is off they won't travel in the same ellipse but they all have different starting angles.
Any clues?
Calculate the incidvidual offsets using this snippet:
// assuming you have your buttons in an array called buttons
for (var i:Number = 0; i < buttons.length; i++){
buttons[i].angleOffset = 360 / buttons.length * i;
}
Set the position each update instead of moving, that way you wont get any drift.
Update each object using this code, incrementing the angle var to get it to spin.
this._x = offsetX + Math.sin((angle + angleOffset) * Math.PI/180) * radius;
this._y = offsetY + Math.cos((angle + angleOffset) * Math.PI/180) * radius / 1.54;
This is almost soved, this piece of script will take the items of the array buttons (can add as many as you want), space them around the ellipse you set (origin + radius), and tween them around it according to the speed you set. The only problem is the spacing isn't even and some are close and some far apart and I don't understand why.
var angle:Number = 0;
var originX:Number = 200;
var originY:Number = 200;
var radiusX:Number = 267.5;
var radiusY:Number = 100;
var steps:Number = 360;
var speed:Number = 3.1415/steps;
var buttons:Array = new Array(this.age,this.ethnicity,this.sex,this.social,this.ability,this.orientation,this.faith);
for (i=0;i<buttons.length;i++) {
buttons[i].onEnterFrame = function() {
moveButtons(this);
controllButtons(this);
};
buttons[i]._order = (360/buttons.length) * (i+1);
}
function moveButtons(e) {
e._anglePhase = angle+e._order;
e._x = originX+Math.sin(e._anglePhase)*radiusX;
e._y = originY+Math.cos(e._anglePhase)*radiusY;
}
function controllButtons(e) {
angle += speed;
if (angle>=360) {
angle -= 360;
}
}
Please note I got the base of this script from http://www.actionscript.org/forums/showthread.php3?t=161830&page=2 converted it to AS2 and made it work from an array.

Resources