Maximum data on screen is 31 point + offset. In my input i have 50 points.
How set more?
Image
Example
JavaScript code and more detail here
It looks like your post is mostly code; please add some more details.
axisX is days, problem here
//array
arr = []
for (let i = 0; i < 50; i++) {
arr.push(i)
}
//object x y
const data = []
const time = new Date().getTime();
const oneDay = 1000*60*60*24
for (let i = 0; i < arr.length; i++) {
const day = new Date( time + ( oneDay * (i+1) ) );
const currentDate = day.getDate()
data.push( {
x: 'day: ' + currentDate,
y: arr[i]
} );
}
// create line chart
chart = anychart.line();
// set chart padding
chart.padding([5, 5, 5, 5]);
// turn on chart animation
chart.animation(false);
// turn on the crosshair
chart.crosshair(false);
// set chart title text settings
const name = 'Name'
chart.title(name);
// set y axis title
chart.yAxis().title('Price');
chart.xScale()
var series;
series = chart.line(data);
series.name('series name');
series.labels().enabled(true).anchor('right-bottom').padding(2);
series.labels().enabled(true).anchor('left-bottom').padding(2);
series.markers(true);
// turn the legend on
chart.legend().enabled(true).fontSize(11).padding([0, 0, 10, 0]);
chart.container('chartContainer');
chart.draw();
It happens because you are using a Cartesian chart which default xScale is Ordinal. The Ordinal scale works with categories, it assumes that all categories are unique. But your data set includes doubling categories, like day: 19, day: 20, etc. So, the next point with the same category name overrides the previous one.
In your case, you should use dateTime scale and real dateTime X coordinates (string date, timestamp in ms, Date class object). For details, check the article.
Related
I'm making a terrain tool.
I made a 2D texture and am using it as a height map.
I want to change a specific part of the heightmap, but I'm having a problem.
I changed certain small parts, but the whole landscape of the texture is changed.
I would like to know the cause of this problem and how to solve it
thank you.
`HeightMap ShaderResourceView Create Code
void TerrainRenderer::BuildHeightmapSRV(ID3D11Device* device)
{
ReleaseCOM(mHeightMapSRV);
ReleaseCOM(m_hmapTex);
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = m_terrainData.HeightmapWidth; //basic value 2049
texDesc.Height = m_terrainData.HeightmapHeight; //basic value 2049
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R16_FLOAT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DYNAMIC;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
texDesc.MiscFlags = 0;
// HALF is defined in xnamath.h, for storing 16-bit float.
std::vector<HALF> hmap(mHeightmap.size());
//current mHeightmap is all zero.
std::transform(mHeightmap.begin(), mHeightmap.end(), hmap.begin(), XMConvertFloatToHalf);
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = &hmap[0];
data.SysMemPitch = m_terrainData.HeightmapWidth * sizeof(HALF);
data.SysMemSlicePitch = 0;
HR(device->CreateTexture2D(&texDesc, &data, &m_hmapTex));
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = texDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = -1;
HR(device->CreateShaderResourceView(m_hmapTex, &srvDesc, &mHeightMapSRV));
}
`HeightMap Texture modifying code
D3D11_MAPPED_SUBRESOURCE mappedData;
//m_hmapTex is ID3D11Texture2D*
HR(m_texMgr.m_context->Map(m_hmapTex, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_WRITE_DISCARD, 0, &mappedData));
HALF* heightMapData = reinterpret_cast<HALF*>(mappedData.pData);
D3D11_TEXTURE2D_DESC heightmapDesc;
m_hmapTex->GetDesc(&heightmapDesc);
UINT width = heightmapDesc.Width;
for (int row = 0; row < width/4; ++row)
{
for (int col = 0; col < width/4; ++col)
{
idx = (row * width) + col;
heightMapData[idx] = static_cast<HALF>(XMConvertFloatToHalf(200));
}
}
m_texMgr.m_context->Unmap(m_hmapTex, D3D11CalcSubresource(0,0,1));
Please refer to the picture below
The lower right area renders the HeightMap texture.
I wanted to edit only 1/4 width and height, but that's all changed.
enter image description here
When the completed heightmap is applied, it works normally.
enter image description here
A texture does not always have the same width and height in memory as the definition suggests. Some textures strides (lines) are oversized. You have to use the Stride Size * Row to calculate the offset to write into.
I am learning p5.js and wanted to generate a "static/noise texture" like so:
This is the code:
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
noiseVal = random(0,1);
stroke(255, noiseVal*255);
point(x,y);
}
}
This produces the desired outcome but it's obviously pretty slow since it has to iterate over every single pixel. What would be a more efficient way of doing this?
Your code is really not the best way to do with p5.js.
Take a look to the p5's pixels array.
When I run the following code, the function that use the pixels array run 100 times faster.
function setup() {
createCanvas(50, 50);
background(255);
let start, time;
start = performance.now();
noise_1();
time = performance.now() - start;
print("noise_1 : " + time);
start = performance.now();
noise_2();
time = performance.now() -start;
print("noise_2 : " + time);
}
// Your code
function noise_1() {
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
noiseVal = random(0,1);
stroke(noiseVal*255);
point(x,y);
}
}
}
// same with pixels array
function noise_2() {
loadPixels();
for (let i=0; i < pixels.length; i+=4){
noiseVal = random(0, 255);
pixels[i] = pixels[i+1] = pixels[i+2] = noiseVal;
}
updatePixels();
}
output :
noise_1 : 495.1
noise_2 : 5.92
To generate a single frame of static, you're going to have to iterate over each pixel. You could make your blocks larger than a single pixel, but that will only reduce the problem, not get rid of it completely.
Instead, you can probably get away with pre-computing a few images of static (let's say 10 or so). Save these as a file or to an off-screen buffer (the createGraphics() function is your friend), and then draw those images instead of drawing each pixel every frame.
I have a 6-DOF robot arm model:
robot arm structure
I want to calculate forward kinematics, so I uses the D-H matrix. the D-H parameters are:
static const std::vector<float> theta = {
0,0,90.0f,0,-90.0f,0};
// d
static const std::vector<float> d = {
380.948f,0,0,-560.18f,0,0};
// a
static const std::vector<float> a = {
-220.0f,522.331f,80.0f,0,0,94.77f};
// alpha
static const std::vector<float> alpha = {
90.0f,0,90.0f,-90.0f,-90.0f,0};
and the calculation :
glm::mat4 Robothand::armForKinematics() noexcept
{
glm::mat4 pose(1.0f);
float cos_theta, sin_theta, cos_alpha, sin_alpha;
for (auto i = 0; i < 6;i++)
{
cos_theta = cosf(glm::radians(theta[i]));
sin_theta = sinf(glm::radians(theta[i]));
cos_alpha = cosf(glm::radians(alpha[i]));
sin_alpha = sinf(glm::radians(alpha[i]));
glm::mat4 Ai = {
cos_theta, -sin_theta * cos_alpha,sin_theta * sin_alpha, a[i] * cos_theta,
sin_theta, cos_theta * cos_alpha, -cos_theta * sin_alpha,a[i] * sin_theta,
0, sin_alpha, cos_alpha, d[i],
0, 0, 0, 1 };
pose = pose * Ai;
}
return pose;
}
the problem I have is that, I can't get the correct result, for example, I want to calculate the transformation matrix from first joint to the 4th joint, I will change the for loop i < 3,then I can get the pose matrix, and I can the origin coordinate in 4th coordinate system by pose * (0,0,0,1).but the result (380.948,382.331,0) seems not correct because it should be move along x-axis not y-axis. I have read many books and materials about D-H matrix, but I can't figure out what's wrong with it.
I have figured it out by myself, the real problem behind is glm::mat, glm::mat is col-type which means columns will be initialized before rows,I changed the code and get the correct result:
for (int i = 0; i < joint_num; ++i)
{
pose = glm::rotate(pose, glm::radians(degrees[i]), glm::vec3(0, 0, 1));
pose = glm::translate(pose,glm::vec3(0,0,d[i]));
pose = glm::translate(pose, glm::vec3(a[i], 0, 0));
pose = glm::rotate(pose,glm::radians(alpha[i]),glm::vec3(1,0,0));
}
then I can get the position by:
auto pos = pose * glm::vec4(x,y,z,1);
Is there a script command that I can specify a particular slice in a LinePlotImageDisplay and do the Align Slice Horizontally by Calibration (or Uncalibrated (channels)) action?
The following scipt is a complete implantation based on example codes provided by BmyGuest. It will align all slices in a LinePlotImageDisplay horizontally either by calibration or by channel (i.e. un-calibrated).
class SliceAlignment : object {
number true, false; // boolean
image imgLPID;
imageDisplay LPID; // line plot image display
number CalculateImageToGroupTransformFactors( object self, image slice_src, image slice_ref, number &relOff, number &relScale ) {
number origin_ref, scale_ref, origin_src, scale_src;
string unit_ref, unit_src;
number calFMT = 0; // origin is expressed in calibrated unit
//
slice_src.ImageGetDimensionCalibration( 0, origin_src, scale_src, unit_src, calFMT );
slice_ref.ImageGetDimensionCalibration( 0, origin_ref, scale_ref, unit_ref, calFMT );
//
relScale = scale_src / scale_ref;
relOff = (origin_src - origin_ref) / scale_ref ;
// check if both images are calibrated in same unit
if( unit_src != unit_ref ) return false
return true;
};
void AlignNthSliceHorizontallyByChannel( object self, number slice_idx ) {
// get current reference slice index
number refSlice_idx = LPID.LinePlotImageDisplayGetSlice();
// get slice ID's (as objects)
object slice_ref = LPID.ImageDisplayGetSliceIDByIndex(refSlice_idx);
object slice_src = LPID.ImageDisplayGetSliceIDByIndex(slice_idx);
number int_offset = 0, int_scale = 1.0; // vertical (intensity) offset and scaling factors
number pos_offset = 0, pos_scale = 1.0; // horizontal (position) offset and scaling factors
LPID.LinePlotImageDisplaySetImageToGroupTransform( slice_src, slice_ref, int_offset, int_scale, pos_offset, pos_scale );
};
void AlignNthSliceHorizontallyByCalibration( object self, number slice_idx ) {
// get current reference slice index
number refSlice_idx = LPID.LinePlotImageDisplayGetSlice();
// get slice ID's (as objects)
object slice_ref = LPID.ImageDisplayGetSliceIDByIndex(refSlice_idx);
object slice_src = LPID.ImageDisplayGetSliceIDByIndex(slice_idx);
number int_offset = 0, int_scale = 1.0; // vertical (intensity) offset and scaling factors
number pos_offset, pos_scale; // horizontal (position) offset and scaling factors
number unit_check = self.CalculateImageToGroupTransformFactors( imgLPID{slice_idx}, imgLPID{refSlice_idx}, pos_offset, pos_scale );
if( unit_check == false ) {
string prompt = "slice #" + slice_idx + " [" + LPID.ImageDisplayGetSliceLabelById( LPID.ImageDisplayGetSliceIDByIndex(slice_idx) ) + "] is calibrated in different unit!";
if( !ContinueCancelDialog( prompt ) ) return
};
LPID.LinePlotImageDisplaySetImageToGroupTransform( slice_src, slice_ref, int_offset, int_scale, pos_offset, pos_scale );
return;
};
void AlignAllSlicesHorizontallyByChannel( object self ) {
number nSlices = LPID.LinePlotImageDisplayCountSlices();
for( number idx = 0; idx < nSlices; idx++ ) self.AlignNthSliceHorizontallyByChannel( idx );
return;
};
void AlignAllSlicesHorizontallyByCalibration( object self ) {
number nSlices = LPID.LinePlotImageDisplayCountSlices();
for( number idx = 0; idx < nSlices; idx++ ) self.AlignNthSliceHorizontallyByCalibration( idx );
return;
};
object init( object self, image img ) {
// check if the image display is correct type
imgLPID := img;
LPID = imgLPID.ImageGetImageDisplay(0);
if( LPID.ImageDisplayGetDisplayType() != 3 ) throw( "Please choose a valid line plot display" );
return self;
};
SliceAlignment( object self ) {
true = 1; false = 0;
result( "SliceAlignment [obj ID:" + self.ScriptObjectGetID().hex() + "] constructured\n" );
};
~SliceAlignment( object self ) {
result( "SliceAlignment [obj ID:" + self.ScriptObjectGetID().hex() + "] destructured\n\n" );
}; };
{; object objAlign = alloc(SliceAlignment);
objAlign.init( GetFrontImage() );
if( OptionDown() ) objAlign.AlignAllSlicesHorizontallyByChannel();
else objAlign.AlignAllSlicesHorizontallyByCalibration(); };
No, there is no single 'convenience' command to achieve this alignment. You will have to create the according function yourself from reading a slices calibration and setting its display-coordinate system. You might find the following (old) tutorial PDF on the FELMI homepage might be useful:
SlicesInLinePlotDisplay.pdf
The following example script might also be useful. It shows how one slice is aligned relative to another slice. (Just on the X-axis)
// All Slices in a LinePlot are grouped into a single 'group'
// Slices can be moved relative to each other by specifying their image-to-group transform,
// and the whole image (i.e. the group) can be moved with respect to the display using the group-to-display transform.
// To set the image-to-group transform of the slice specified by 'slice_id', with respect to the slice specified by 'ref_id'
// use the command:
// LinePlotImageDisplaySetImageToGroupTransform( LinePlotImageDisplay lpid, ScriptObject slice_id, ScriptObject ref_id, double off_val, double scale_val, double off_dim_0, double scale_dim_0 )
/*********************************************************/
// Create 2 LinePlots and add them into one display
// (Initially they are aligned by their calibrations)
number sc1 = 1
number of1 = -50
number sc2 = 2
number of2 = -20
image sl1 := realImage("S1",4,300)
image sl2 := realImage("S2",4,300)
sl1 = (iwidth-icol)/iwidth
sl2 = (iwidth-icol)/iwidth
sl1[0,50,1,60] = 1
sl1[0,250,1,260] = 1
sl2[0,10,1,15] = 1
sl2[0,110,1,115] = 1
// Adding Calibrations
sl1.ImageSetDimensionCalibration(0,of1,sc1,"CH",0)
sl2.ImageSetDimensionCalibration(0,of2,sc2,"CH",0)
sl1.DisplayAt(20,30)
sl2.DisplayAt(750,30)
OKDialog( "Put into one Display" )
imageDisplay disp = sl1.ImageGetImageDisplay(0)
disp.ImageDisplayAddImage( sl2, "S2") // When added like this, the slices are automatically aligned by their respective calibration!
disp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
object ref_id = disp.ImageDisplayGetSliceIDByIndex(0) // Slice 0
object slice_id = disp.ImageDisplayGetSliceIDByIndex(1) // Slice 1
OKDialog("Now align by channels (i.e. undo any relative sclice alignment)")
// Simply set the relative "shifts" and "scales" to 0 and 1.
disp.LinePlotImageDisplaySetImageToGroupTransform( slice_id, ref_id, 0, 1, 0, 1 )
OKDialog("Now align by chalibration ")
number relScale = sc2/sc1
number relOff = of2-of1
disp.LinePlotImageDisplaySetImageToGroupTransform( slice_id, ref_id, 0, 1, relOff, relScale )
I want to position x,y,z labels (sprites) on the axis I have in my scene. The problem is that zooming with the camera , should result to also moving the particles analogously so they stay in the side of the "screen".
So I just want to find a way to always know where the lines of x,y,z are out of the camera to update the labels' positions :
fiddle (here they are just static).
the pseudocode of what I might need to acheve that :
function update() {
var pointInLinePosition = calculateLastVisiblePointOfXline();
xSprite.position.set(pointInLinePosition.x, pointInLinePosition.y, pointInLinePosition.z);
}
function calculateLastVisiblePointOfXline(){
}
I found a solution which is satisfying enough (for me at least) but not perfect.
Firstly I create a frustum using the scene's camera :
var frustum = new THREE.Frustum();
frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse ) );
Then, I check if any of the planes of the frustum intersects with any of the lines I have in the scene :
for (var i = frustum.planes.length - 1; i >= 0; i--) {
var py = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(1000,0,0) ) ) ;
if(py !== undefined) {
ySprite.position.x = py.x-1 ;
}
var px = frustum.planes[i].intersectLine( new THREE.Line3( new THREE.Vector3(0,0,0), new THREE.Vector3(0,0,1000) ) ) ;
if(px !== undefined) {
xSprite.position.z = px.z-1 ;
}
};
If there is an intersection, I update the labels' position using the return value of the intersectLine() which is the point of intersection.
This is the updated fiddle : fiddle
I hope that helps. In my case it fit.
A correct test for intersections also has to make sure that the intersection point is actually within the frustum as the frustum planes extend indefinitely, potentially leading to false positive intersections.
One naive way of validating intersections, is checking the distance of the intersection to all planes. If the distance is greater or equal to zero, the point is within the frustum.
Adjusted code snipped from ThanosSar's answer:
const intersect = point => frustum.planes
.map(plane =>
plane.intersectLine(new THREE.Line3(new THREE.Vector3(0, 0, 0), point))
)
.filter(sect => sect != null)
.filter(sect => frustum.planes.every(plane => plane.distanceToPoint(sect) >= -0.000001))[0];
const iy = intersect(new THREE.Vector3(1000, 0, 0));
if (iy != null)
ySprite.position.x = iy.x - 1;
const ix = intersect(new THREE.Vector3(0, 0, 1000));
if (ix != null)
xSprite.position.z = ix.z - 1;
(The comparison is with >= -0.000001 to account for floating point rounding errors)
Fiddle