Given 3 or more numbers or vectors, how do I interpolate between them based on a percentage? - math

I want to know the most basic math principles I need to interpolate a value between 3 or more other values, based on a linear percentage; as it would be applicable in programming.
For example, say I have "0", "100", "200", and I want the number that's at "50%". The math would then return something like "100" because 100 is at 50%.
Another example: I have 3 points somewhere in 3D space. If I do "75%" then the result would be a point that is exactly halfway between point 2 and 3, or if I do "25%" then it'll be half-way between 1 and 2.
Game engines like Unity use something like this for blending between multiple animations on a character, for another example.
What I've brainstormed so far is that I would somehow take the input value and find whatever the 2 neighboring "points" are closest to it (much harder in 3D or 2d space but manageable in 1d), then simply lerp between those two- but that requires me to figure out what percentage both of those points are at individually, and remap from "0 to 100%" to "A% to B%". I think it would work but It seems kind of complicated to me.
If possible, I'd like answers to include a C# example or language-agnostic psuitocode just so I can understand the math.

simple example for scalar float objects using piecewise linear interpolation:
int n=3; // number of your objects
float x[n]={ 0.5,2.0,10.0 }; // your objects
float get_object(float t) // linearly interpolate objects x[] based in parameter t = <0,1>, return value must be the same type as your objects
{
int ix;
float x0,x1; // the same type as your objects
// get segment ix and parameter t
t*=n; ix=floor(t); t-=ix;
// get closest known points x0,x1
x0=x[ix]; ix++;
if (ix<n) x1=x[ix]; else return x0;
// interpolate
return x0+(x1-x0)*t;
}
so if t=0 it returns first object in the x[] if it is t=1 is returns last and anything in between is linearly interpolated ... The idea is just to multiply our t by number of segments or point (depend on how you handle edge cases) which integer part of the result will give us index of closest 2 objects to our wanted one and then the fractional part of multiplied t will give us directly interpolation parameter in range <0,1> between the two closest points...
In case you objects are not with the same weight or are not uniformly sampled then you need to add interpolation with weights or use higher order polynomial (quadratic,cubic,...).
You can use this for "any" type T of objects you just have to implement operations T+T , T-T and T*float if they are not present.

If your gameObjects is at the same line try this code.
public Transform objStart;
public Transform objEnd;
public Transform square;
public float distance;
//percent .5 means 50%
[Range(0f,1f)]
public float percent;
public Vector3 distancePercentPosition;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//get distance between two object
distance = Vector3.Magnitude(objEnd.position - objStart.position);
//get position based on percent;
distancePercentPosition = (objEnd.position - objStart.position).normalized * percent * distance;
square.position = objStart.position + distancePercentPosition;
}
once you get the position between lines you can now map your gameobject in each position based on percent.

Related

What unit is `getFitnessScore()` in the IterativeClosestPoint class from PCL returning?

I use the pcl::IterativeClosestPoint method from the Point-Cloud-Library.
As of right now it seems that the documentation of it is offline.
Here in google cache. And also a tutorial.
There is a possibility to call icp.getFitnessScore() to get the mean squared distances from the points of the two clouds. I just can't find information on what kind of unit this is indicated. Does anyone knows what the number I get there means? For example output for me was: 0,0003192. This seems to be low, but I have no clue if it is meters, centimeters, feet, or whatever.
Thank you very much.
what kind of unit is icp.getFitnessScore() used?
Like Joy said in his comment, the unit is the same as your input data.
For example, your input point cloud might comes from a obj file. And a point will be stored like v 9.322 -1.0778 0.44997. The number returned by icp.getFitnessScore() will have the same unit as the point's coordinate.
Does anyone knows what the number I get there means?
The number you get represents the mean squared distance from each point in source to its closest point in target.
That is to say, if you assume every point in source has a corresponding point in target, and the correspondence set comes from closest point data association, then the number represents the mean squared distance between all correspondences. That can be seen from the source code below.
To make more sense of the function, you might want to filter out correspondences that have a large distance between them. (The two point cloud might only partially overlap.) And the function actually has an optional parameter max_range that does this.
The method getFitnessScore() is defined in pcl::Registration, the base class of pcl::IterativeClosestPoint. The optional parameter max_range is defaulted to be std::numeric_limits<double>::max(), as you can see in the definition:
/** \brief Obtain the Euclidean fitness score (e.g., sum of squared distances from the source to the target)
* \param[in] max_range maximum allowable distance between a point and its correspondence in the target
* (default: double::max)
*/
inline double
getFitnessScore (double max_range = std::numeric_limits<double>::max ());
And the source code of this function is:
template <typename PointSource, typename PointTarget, typename Scalar> inline double
pcl::Registration<PointSource, PointTarget, Scalar>::getFitnessScore (double max_range)
{
double fitness_score = 0.0;
// Transform the input dataset using the final transformation
PointCloudSource input_transformed;
transformPointCloud (*input_, input_transformed, final_transformation_);
std::vector<int> nn_indices (1);
std::vector<float> nn_dists (1);
// For each point in the source dataset
int nr = 0;
for (size_t i = 0; i < input_transformed.points.size (); ++i)
{
// Find its nearest neighbor in the target
tree_->nearestKSearch (input_transformed.points[i], 1, nn_indices, nn_dists);
// Deal with occlusions (incomplete targets)
if (nn_dists[0] <= max_range)
{
// Add to the fitness score
fitness_score += nn_dists[0];
nr++;
}
}
if (nr > 0)
return (fitness_score / nr);
else
return (std::numeric_limits<double>::max ());
}

Moving along a path of straight line segments at constant speed

I have a list of vector points, which define a path of straight line segments to be followed by an object. Currently, I do linear interpolation to animate motion along the path like this:
public class Demo
{
public float speed = 1;
private List<Vector3> points;
private float t; // [0..1]
private Vector3 Evaluate(float t)
{
// Find out in between which points we currently are
int lastPointIndex = GetLast(t);
int nextPointIndex = GetNext(t);
// Obviously, I need to somehow transform parameter t
// to adjust for the individual length of each segment.
float segmentLength = GetLength(lastPointIndex, nextPointIndex);
// But how would I do this?
return Vector3.Lerp(points[lastPointIndex], points[nextPointIndex], t);
}
public void Update()
{
// Curve parameter t moves between 0 and 1 at constant speed.
t = Mathf.PingPong(Time.time * speed, 1);
// Then just get the evaluated position for the curve time, but
// this gives variant speed if points are not evenly spaced.
Vector3 position = Evaluate(t);
SetObjectPosition(position);
}
}
I realize, that to achieve constant speed, I need to rescale the parameter t to account for the length of each segment, but I seem to be unable to find out exactly how.
I also know, that I could approximate the path by moving towards the next point at my desired speed and only change direction, once I'm in close proximity or keep track of t as well and change direction once it moves over the next segment, but this seems hacky, when I actually know the exact length of each segment and should be able to interpolate this exactly.
That's actually quiet easy. First, define a speed you want for your object. For example, 6 units per second. That means if a line segment has a length of 6 units then your object will take 1 second to go from its start to its end point. This also means that if you have a line segment that is half that length (i.e. 3 units) it will take the object 0.5 second to cross it. So, what you have to do is calculate the length of all your line segments and divide that by the speed you want to go (3/6 = 0.5 = scaleFactor). Then instead of interpolating between 0 and 1, interpolate between 0 and 1*scaleFactor. Your code then becomes:
public class Demo
{
public float speed = 1;
private List<Vector3> points;
private float t; // [0..1]
private Vector3 Evaluate(float t)
{
// Find out in between which points we currently are
int lastPointIndex = GetLast(t);
int nextPointIndex = GetNext(t);
float segmentLength = GetLength(lastPointIndex, nextPointIndex);
float scaleFactor = segmentLength/speed;
// note that I divided t by scaleFactor instead of multiplication.
// That's because Lerp always takes an interval of [0..1]. So, we
// adjust the curve parameter instead.
return Vector3.Lerp(points[lastPointIndex], points[nextPointIndex], t/scaleFactor);
}
public void Update()
{
// Curve parameter t moves between 0 and 1 at constant speed.
t = Mathf.PingPong(Time.time * speed, 1);
// Then just get the evaluated position for the curve time, but
// this gives variant speed if points are not evenly spaced.
Vector3 position = Evaluate(t);
SetObjectPosition(position);
}
}

How can I get transform matrix for QQuickItem?

I worked for a long time with QGraphicsItem and it has transform() function. Now I wont to do same thing with QQuickItem but unfortunately it misses transform(). So my question - how can I get transform matrix for QQuickItem?
Actually the QQuickItem provides the transform() method, however it returns the list of all transformations assigned to given item. It is because multiple transformations can be assigned to a single Item. The return type of QQuickItem::transform is QQmlListProperty<QQuickTransform> — it is a wrapper to QML list<Transform> type (see documentation for Item). It can be iterated over, yielding QQuickTransform * elements. QQuickTransform is a base class for a transformation that provides a virtual method applyTo taking a QMatrix4x4 * argument and applying the transformation upon it.
The QML allows instantiating several QQuickTransform subclasses (for translation, rotation and scale) and user is allowed to defined custom transformations (eg. for skew).
To obtain a single transformation matrix you need, you have to start with identity matrix and sequentially apply all the transformations of given QQuickItem.
QMatrix4x4 transformOfItem(QQuickItem *item)
{
QQmlListProperty transformations = item->transform();
const int count = transformations.count(&transformations);
// Prepare result structure, it will be default-initialized to be an identity matrix
QMatrix4x4 transformMatrix;
// Apply sequentially all transformation from the item
for(int i = 0; i applyTo(&transformMatrix);
}
return transformMatrix;
}
Note that the function returns a tranformation matrix as QMatrix4x4 — it is more than old QTransform that was based on 3x3 transformation matrix, so it cannot be converted without loss. If you want, you may use QMatrix4x4::toAffine to get the QMatrix (3x3) and use it to create QTransform object. However, if your QQuickItem transformations contain non-affinic elements, they will be lost.
Edit
There's one more thing to note: the method I posted works only for transformations defined by assigning to transform property. It does not check for scale and rotation properties. If you use them, you should check their values with appropriate QQuickItem methods and adjust returned matrix to include these two additional tranformations.
Here's a correct solution, based on the code provided by Michael earlier, but fixed to work actually, so you don't have to spend 20 minutes figuring out how to use QQmlListProperty
QMatrix4x4 YourQQuickItem::get_model_matrix() {
QMatrix4x4 result;
// Compose model matrix from our transform properties in the QML
QQmlListProperty<QQuickTransform> transformations = transform();
const int count = transformations.count(&transformations);
for (int i=0; i<count; i++) {
QQuickTransform *transform = transformations.at(&transformations, i);
transform->applyTo(&result);
}
return result;
}
In my use case I use this to get the model matrix for my object, then multiply together with view and projection matrixes to calculate the model-view-projection matrix.
The QSGTransformNode class implements transformations in the scene graph. In updatePaintNode function, argument updatePaintNodeData provides a pointer to the QSGTransformNode associated with this QQuickItem.
QSGNode *MyQuickItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data)
{
QSGTransformNode *transformNode = data->transformNode;
qDebug() << transformNode->matrix();

Usage of Map and Translate Functions in Processing

New to Processing working on understanding this code:
import com.onformative.leap.LeapMotionP5;
import java.util.*;
LeapMotionP5 leap;
LinkedList<Integer> values;
public void setup() {
size(800, 300);
frameRate(120); //Specifies the number of frames to be displayed every second
leap = new LeapMotionP5(this);
values = new LinkedList<Integer>();
stroke(255);
}
int lastY = 0;
public void draw() {
**translate(0, 180)**; //(x, y, z)
background(0);
if (values.size() >= width) {
values.removeFirst();
}
values.add((int) leap.getVelocity(leap.getHand(0)).y);
System.out.println((int) leap.getVelocity(leap.getHand(0)).y);
int counter = 0;
** for (Integer val : values)** {
**val = (int) map(val, 0, 1500, 0, height);**
line(counter, val, counter - 1, lastY);
point(counter, val);
lastY = val;
counter++;
}
** line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); //(x1, y1, x2, y2)**
}
It basically draw of graph of movement detected on the y axis using the Leap Motion sensor. Output looks like this:
I eventually need to do something similar to this that would detect amplitude instead of velocity simultaneously on all 3 axis instead of just the y.
The use of Map and Translate are whats really confusing me. I've read the definitions of these functions on the Processing website so I know what they are and the syntax, but what I dont understand is the why?! (which is arguably the most important part.
I am asking if someone can provide simple examples that explain the WHY behind using these 2 functions. For instance, given a program that needs to do A, B, and C, with data foo, y, and x, you would use Map or Translate because A, B, and C.
I think programming guides often overlook this important fact but to me it is very important to truly understanding a function.
Bonus points for explaining:
for (Integer val : values) and LinkedList<Integer> values; (cant find any documentation on the processing website for these)
Thanks!
First, we'll do the easiest one. LinkedList is a data structure similar to ArrayList, which you may be more familiar with. If not, then it's just a list of values (of the type between the angle braces, in this case integer) that you can insert and remove from. It's a bit complicated on the inside, but if it doesn't appear in the Processing documentation, it's a safe bet that it's built into Java itself (java documentation).
This line:
for (Integer val : values)
is called a "for-each" or "foreach" loop, which has plenty of very good explanation on the internet, but I'll give a brief explanation here. If you have some list (perhaps a LinkedList, perhaps an ArrayList, whatever) and want to do something with all the elements, you might do something like this:
for(int i = 0; i < values.size(); i++){
println(values.get(i)); //or whatever
println(values.get(i) * 2);
println(pow(values.get(i),3) - 2*pow(values.get(i),2) + values.get(i));
}
If you're doing a lot of manipulation with each element, it quickly gets tedious to write out values.get(i) each time. The solution would be to capture values.get(i) into some variable at the start of the loop and use that everywhere instead. However, this is not 100% elegant, so java has a built-in way to do this, which is the for-each loop. The code
for (Integer val : values){
//use val
}
is equivalent to
for(int i = 0; i < values.size(); i++){
int val = values.get(i);
//use val
}
Hopefully that makes sense.
map() takes a number in one linear system and maps it onto another linear system. Imagine if I were an evil professor and wanted to give students random grades from 0 to 100. I have a function that returns a random decimal between 0 and 1, so I can now do map(rand(),0,1,0,100); and it will convert the number for me! In this example, you could also just multiply by 100 and get the same result, but it is usually not so trivial. In this case, you have a sensor reading between 0 and 1500, but if you just plotted that value directly, sometimes it would go off the screen! So you have to scale it to an appropriate scale, which is what that does. 1500 is the max that the reading can be, and presumably we want the maximum graphing height to be at the edge of the screen.
I'm not familiar with your setup, but it looks like the readings can be negative, which means that they might get graphed off the screen, too. The better solution would be to map the readings from -1500,1500 to 0,height, but it looks like they chose to do it a different way. Whenever you call a drawing function in processing (eg point(x,y)), it draws the pixels at (x,y) offset from (0,0). Sometimes you don't want it to draw it relative to (0,0), so the translate() function allows you to change what it draws things relative against. In this case, translating allows you to plot some point (x,0) somewhere in the middle of the screen, rather than on the edge.
Hope that helps!

Map a Matrix to a Circular Frame Image

I have a matrix and o want to map it to a circular frame. Each element in matrix should be mapped to a predefined position on the circular frame. What i am really do is dealing with the human brain signals recorded from different electrodes installed over the skull. This is the final plot i want to get:
http://www.ihr.mrc.ac.uk/img/research/2009/3/scan-banner.jpg
Any Sugestion?
Please, correct me if I'm wrong. I don't know what kind of data these electrodes are able to retrieve, but in any case, I think you can view them in two different natures: first, sampled data (a class that encapsulates all information gathered through one specific electrode) and second, a geographically mapping object, binding the data from each electrode to one specific location.
As for the first part, you can design whatever class you wish, according to your needs. This class may have but a single double value (like intensity or electric level, or whatever) or a complete set of variables or even other classes arranged in such a way that represent what you need.
As for the second part, as you want to map the data retrieved from each electrode into a pre-determined point in a circular area, I think a class having an horizontal and a vertical positioning value is good. This can be a java.awt.Point (which can map to the real X and Y position of the point you wish) or a custom class (non-related to any domain) with the two X and Y variables, that can translate to a real X and Y coordinate in the final image.
Something like that
public class Position {
private int x;
private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
and
public class Sample {
private double electricalLevel;
private Position position;
public double getElectricalLevel() {
return electricalLevel;
}
public void setElectricalLevel(double electricalLevel) {
this.electricalLevel = electricalLevel;
}
public Position getPosition() {
return position;
}
public void setPosition(Position position) {
this.position = position;
}
}
Something like that.
Then you'll have to instantiate each Sample, map it to a Position instance and keep updating the values.
As for the mapping to the correct Position, you can have all the positions pre-calculated and entered as literals, or calculated from a positioning function. I think the pre-calculated positions are ok, as they are not prone to changing...
Then you'll have something like:
Sample s1 = new Sample();
s1.setPosition(new Position(100, 100));
Sample s2 = new Sample();
s2.setPosition(new Position(150, 80));
and so on, for each electrode.
As for the drawing itself, you'll have to dig into java imaging. This will not be so simple, because you're not really only plotting the points themselves. Actually, the colour of each point and its surrounding area will be a function of the sampled data, if I'm correct, as the colour seems to be reflecting the sampled data from that brain region.
To make things worse, the boundary areas between multiple points will influence each other, so that a colour gradient will be generated.
I suggest you first focus in the given scenario and that you ask about the painting and java imaging issue in other question.
Sorry, this is a really general answer, but it's as far as I can go with many assumptions and without knowing what exactly you're dealing with. I hope it helps, though.

Resources