Im using shutterstock rickshaw chart library to visualize some sensordata via ajax-php-sql.
In all examples, rickshaw relies on data for the series in the form
[ [ { x: xval1, y: yval1}, { x: xval2, y: yval2}, ...]
[ { x: xval1, y: yvalS2_1}, { x: xval2, y: yvalS2_2}, ...]
]
which I find a bit tedious compared to e.g. xmgrace's 'nxy' mode:
one x-column, n y-columns - which is exactly what I get from the sql query (because my sensors are sampled at identic timestamps).
So the question would be is it possible to privide rickshaw's data input always the same x-data vector and individual y-data vectors, held in an array?
Thank You!
Alex
Related
I have a csv of lat., long., and altitude data from flight 24.
I want to make a path for an object to follow in blender, but the path has to be generated from the above data.
I also want to import a 3D-model of the place where the aircraft flew over.
The problem is I need to use blender 2.77 because the another add-on I want to use only supports v. 2.77. Add-ons like blender-osm and blender-gis only supports the most up to date version of blender.
Lets say you have x y z coordinates for each point of a path then you can easily able to create a path curve using bpy. Here is an example:
import bpy
def create_curve(coords_list):
crv = bpy.data.curves.new('crv', 'CURVE')
crv.dimensions = '3D'
spline = crv.splines.new(type='NURBS')
spline.points.add(len(coords_list) - 1)
for p, new_co in zip(spline.points, coords_list):
p.co = (new_co + [1.0])
obj = bpy.data.objects.new('object_name', crv)
bpy.data.scenes[0].collection.objects.link(obj)
cords_list = [
[0,0,0],
[1, 0, 1],
[2, 0, -1],
[0, 0, 2]
]
create_curve(cords_list)
Output:
I am using chartjs 2.9.3. I want to have linear scale for x axis for bar plots. It should work just like any linear scale of line plots representing negative, decimal, positive values.
I have managed to create almost similar scale here using this options.
scales: {
xAxes: [
{
type: "time",
time: {
parser: "Y",
unit: "year",
displayFormats: {
year: "Y"
}
},
}
]
},
But it is not working for decimal values, when dataset has negative x values, it is just rounding off to integer and placing the bar at that position.
How can represent decimal values as well?
Chartjs >=3.0.0 has introduced linear scale for bar plots. But this version has some other bugs in it so I am stuck with 2.9.3 version
I don't recommend to change the axis type to time, as this will introduce several other issues given that there are not "fractional times". And adding support for it is not that easy.
The best bet is to create your own labels with a custom function. For example:
const f = () => {
let a = [];
for (let n = -30; n <= 30; n++) {
a.push(n / 100 + "");
}
return a;
};
To generate from -3.00 to +3.00 (zeros representing decimal places). The bigger the numbers 30 and 100 the bigger the "resolution" of your linear scale.
Demo: https://codesandbox.io/s/react-chartjs-2-example-forked-26bbx?file=/src/index.js
Along with predefined animation curves these is an option to set a timing curve using timingcurve(::::duration:).
What is the meaning of its parameters (c0x,c0y, c1x, c1y)? How is the curve built? Documentation is lacking.
I'm only guessing as much as I can with the information we're given.
From the docs...
static func timingCurve(_ c0x: Double, _ c0y: Double, _ c1x: Double, _ c1y: Double, duration: Double = 0.35) -> Animation
It looks like the four numbers are actually a pair of x, y coordinates.
c0 = (c0x, c0y)
c1 = (c1x, c1y)
We also know that this is going to generate an easing curve which will start at time 0, animation %age 0 and end at time 1, animation %age 100.
So... I'm guessing these parameters are control points for a cubic bezier curve.
We would have four control points.
The start point (0, 0)
The first parameter c0
The second parameter c1
The end point (1, 1)
So, you need to provide the control points to generate the cubic curve that would describe the timing curve that you would like to use.
You can use this website https://cubic-bezier.com/#.17,.67,.82,.38 to have a look at how those properties change the curve.
As a basic example a timing curve like "ease-in-out" with a duration of 1 second would use parameters like...
timingCurve(0.42, 0, 0.58, 1, duration: 1.0)
Hope that helps.
I need to draw a smooth curve through some points, which I then want to show as an SVG path. So I create a B-Spline with scipy.interpolate, and can access some arrays that I suppose fully define it. Does someone know a reasonably simple way to create Bezier curves from these arrays?
import numpy as np
from scipy import interpolate
x = np.array([-1, 0, 2])
y = np.array([ 0, 2, 0])
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]
tck, u = interpolate.splprep([x, y], s=0, per=True)
cx = tck[1][0]
cy = tck[1][1]
print( 'knots: ', list(tck[0]) )
print( 'coefficients x: ', list(cx) )
print( 'coefficients y: ', list(cy) )
print( 'degree: ', tck[2] )
print( 'parameter: ', list(u) )
The red points are the 3 initial points in x and y. The green points are the 6 coefficients in cx and cy. (Their values repeat after the 3rd, so each green point has two green index numbers.)
Return values tck and u are described scipy.interpolate.splprep documentation
knots: [-1.0, -0.722, -0.372, 0.0, 0.277, 0.627, 1.0, 1.277, 1.627, 2.0]
# 0 1 2 3 4 5
coefficients x: [ 3.719, -2.137, -0.053, 3.719, -2.137, -0.053]
coefficients y: [-0.752, -0.930, 3.336, -0.752, -0.930, 3.336]
degree: 3
parameter: [0.0, 0.277, 0.627, 1.0]
Not sure starting with a B-Spline makes sense: form a catmull-rom curve through the points (with the virtual "before first" and "after last" overlaid on real points) and then convert that to a bezier curve using a relatively trivial transform? E.g. given your points p0, p1, and p2, the first segment would be a catmull-rom curve {p2,p0,p1,p2} for the segment p1--p2, {p0,p1,p2,p0} will yield p2--p0, and {p1, p2, p0, p1} will yield p0--p1. Then you trivially convert those and now you have your SVG path.
As demonstrator, hit up https://editor.p5js.org/ and paste in the following code:
var points = [{x:150, y:100 },{x:50, y:300 },{x:300, y:300 }];
// add virtual points:
points = points.concat(points);
function setup() {
createCanvas(400, 400);
tension = createSlider(1, 200, 100);
}
function draw() {
background(220);
points.forEach(p => ellipse(p.x, p.y, 4));
for (let n=0; n<3; n++) {
let [c1, c2, c3, c4] = points.slice(n,n+4);
let t = 0.06 * tension.value();
bezier(
// on-curve start point
c2.x, c2.y,
// control point 1
c2.x + (c3.x - c1.x)/t,
c2.y + (c3.y - c1.y)/t,
// control point 2
c3.x - (c4.x - c2.x)/t,
c3.y - (c4.y - c2.y)/t,
// on-curve end point
c3.x, c3.y
);
}
}
Which will look like this:
Converting that to Python code should be an almost effortless exercise: there is barely any code for us to write =)
And, of course, now you're left with creating the SVG path, but that's hardly an issue: you know all the Bezier points now, so just start building your <path d=...> string while you iterate.
A B-spline curve is just a collection of Bezier curves joined together. Therefore, it is certainly possible to convert it back to multiple Bezier curves without any loss of shape fidelity. The algorithm involved is called "knot insertion" and there are different ways to do this with the two most famous algorithm being Boehm's algorithm and Oslo algorithm. You can refer this link for more details.
Here is an almost direct answer to your question (but for the non-periodic case):
import aggdraw
import numpy as np
import scipy.interpolate as si
from PIL import Image
# from https://stackoverflow.com/a/35007804/2849934
def scipy_bspline(cv, degree=3):
""" cv: Array of control vertices
degree: Curve degree
"""
count = cv.shape[0]
degree = np.clip(degree, 1, count-1)
kv = np.clip(np.arange(count+degree+1)-degree, 0, count-degree)
max_param = count - (degree * (1-periodic))
spline = si.BSpline(kv, cv, degree)
return spline, max_param
# based on https://math.stackexchange.com/a/421572/396192
def bspline_to_bezier(cv):
cv_len = cv.shape[0]
assert cv_len >= 4, "Provide at least 4 control vertices"
spline, max_param = scipy_bspline(cv, degree=3)
for i in range(1, max_param):
spline = si.insert(i, spline, 2)
return spline.c[:3 * max_param + 1]
def draw_bezier(d, bezier):
path = aggdraw.Path()
path.moveto(*bezier[0])
for i in range(1, len(bezier) - 1, 3):
v1, v2, v = bezier[i:i+3]
path.curveto(*v1, *v2, *v)
d.path(path, aggdraw.Pen("black", 2))
cv = np.array([[ 40., 148.], [ 40., 48.],
[244., 24.], [160., 120.],
[240., 144.], [210., 260.],
[110., 250.]])
im = Image.fromarray(np.ones((400, 400, 3), dtype=np.uint8) * 255)
bezier = bspline_to_bezier(cv)
d = aggdraw.Draw(im)
draw_bezier(d, bezier)
d.flush()
# show/save im
I didn't look much into the periodic case, but hopefully it's not too difficult.
In ARKit, when I perform a hit-test, I get back an instance of ARHitTestResult. One of the properties of this is worldTransform, which I understand contains a 4x4 transformation matrix of the position of the object – simd_float4x4.
As someone who is very unfamiliar with linear algebra and 3D graphics, how would I edit this matrix to, say, increase its y coordinate by 0.05?
If there is a blog post or something I could look at that would help me wrap my head around this, please let me know. I am not sure what terms I should be googling.
Sorry if my question is full of misunderstandings! As you can probably tell, I am not too familiar with these concepts.
Thank you to anyone who helps.
EDIT: The original question is best addressed by just adding 0.05 to the y component of the node's position. However, the original answer below does address a bit about composing transformation matrices, if that is something you are interested in.
======================================================================
If you want to apply an operation to a matrix, the most immediately simple way is to make a matrix that does that operation, and then multiply your original matrix by that new matrix.
For a translation, assuming you want to translate by x, y, z, you can do this:
let translation = simd_float4x4(
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(x, y, z, 1)
)
Note that this is just an identity matrix (1 down the diagonal) with the last column (!!!important, the float4s above are COLUMNS, not ROWS, as they would visually seem) set to contain the x/y/z values. You can research further into homogeneous coordinates, but think of this as just how a translation is represented.
Then, in simd, just do this: let newWorldTransform = translation * oldWorldTransform and you will have the old world transform translated by your x/y/z translation values (in your example, [x, y, z] = [0, 0.05, 0]).
However, it may be worth exploring why you want to edit your hit test results. I cannot think of a practical use case for that, so maybe if you explain a bit more about what you are trying to do I could suggest a more intuitive way to do it.
Matrices in 3D graphics is a regular way to translate, rotate, scale and shear 3D objects. In ARKit, RealityKit and SceneKit for consistent linear transformations you need to use simd_float4x4-like matrices:
var myMatrix: simd_float4x4
Translation 4x4 Matrix has 16 elements inside – 4 elements (float4) by 4 columns. Columns indices are 0, 1, 2 and 3. Translation matrix uses the fourth column with index 3.
SceneKit example
Use the following code to place your model 25 cm above its default position SCNVector3(0,0,0):
let sphereNode = SCNNode()
sphereNode.geometry = SCNSphere(radius: 1.0)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red
scene.rootNode.addChildNode(sphereNode)
var translation = matrix_identity_float4x4
translation.columns.3.y = 0.25
sphereNode.simdWorldTransform = translation
RealityKit example
let model = ModelEntity(mesh: .generateBox(size: 0.3))
let anchor = AnchorEntity()
anchor.addChild(model)
let currentMatrix = anchor.transform.matrix
var positionMatrix = simd_float4x4()
positionMatrix.columns.3.y = 0.25
let transform = simd_mul(currentMatrix, positionMatrix)
anchor.move(to: transform, relativeTo: model, duration: 1.0)