I'm learning QtCharts.
I need to zoom a chart, and adjust the range of the axis-Y accordingly, in order to make the logical visible part of the line can be completely plotted in the real visible area of the ChartView.
For example:
auto chart = new QtCharts::QChart;
auto lines = new QtCharts::QLineSeries;
QDateTime dt = QDateTime::currentDateTime();
for( int i = 0; i < 100; ++i ) {
lines->append( dt.toMSecsSinceEpoch(), std::pow( i, 2 ) );
dt = dt.addMSecs( 500 );
}
chart->addSeries( lines );
auto axisX = new QtCharts::QDateTimeAxis( chart );
axisX->setTickCount( 13 );
axisX->setFormat( "ss.zzz" );
chart->addAxis( axisX, Qt::AlignBottom );
lines->attachAxis( axisX );
auto axisY = new QtCharts::QValueAxis( chart );
axisY->setLabelFormat( "%i" );
chart->addAxis( axisY, Qt::AlignLeft );
lines->attachAxis( axisY );
auto cv = new QtCharts::QChartView( chart );
setCentralWidget( cv );
resize( 800, 600 );
cv->show();
At beginning, my chart looks like this:
When zooming in, I call "zoomin" method of chart:
chart->zoomIn();
But the line would "goes out of the visible area of the View", like this:
I want it look like this:
So, I called the scroll method of chart:
chart->scroll( 0, -50 );
But it obviously cannot be applied within my product program,
As:
I don't wana "repaint" multi-times, as I belive that the chart would
be repaint after any calls to axisY->setRange and chart->zoom, and
chart->scroll, and so on...
How should I finger out the arguments of the axisY->setRange to
adjust it? I looked through the members of
QLineSeries/QChart/QValue/QChartView, but I didn't found a way to calculate the new max/min value of the axis-Y.
I belive that there must be a method can resolve my problem, but I don't know.
Thanks! Sorry for my poor English.
Related
I have found many examples of three.js reflecting images, but is at all possible to reflect lines, triangles and shapes? I want to create a mirror pyramid that reflects lines.
For example: http://www.gus.graphics/buffer.html >This page has lots of lines.
I want to reflect them onto a 3d shape that sits in the middle.
For example: http://www.gus.graphics/ball1.html > This page has a mirror ball.
These are the sort of lines of code I am looking at. Not sure if it's even possible.
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } )
shader.uniforms[ "tCube" ].value = textureCube;
At the moment that code above is taking in a bunch of images "urls", but as you probably know by now I want to reflect the geometry in the first link I provided.
You can take a look at THREE.CubeCamera. It creates 6 cameras that render to a WebGLRenderTargetCube and then use it as envMap. An example would be:
//Create cube camera
var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
scene.add( cubeCamera );
//Create material and mesh
var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
var car = new Mesh( carGeometry, chromeMaterial );
scene.add( car );
//Update the render target cube
car.setVisible( false );
cubeCamera.position.copy( car.position );
cubeCamera.updateCubeMap( renderer, scene );
//Render the scene
car.setVisible( true );
renderer.render( scene, camera );
See this: http://threejs.org/docs/#Reference/Cameras/CubeCamera
There are also examples usage here:
http://threejs.org/examples/#webgl_materials_cubemap_dynamic
http://threejs.org/examples/#webgl_materials_cubemap_dynamic2
I'm seeing a weird filtering issue in using dc.js to draw stacked bar charts. Selecting a filtering area by brushing the chart sometimes starts the selection outside of the axis (figure b), or only lets me select the brush on steps that are integers (i.e. in figure a&b I can only select for example range 2.0-3.0 and or 2.0-4.0 etc). On sub-integer x-axis scales no brushing selection is seen.
Basically
scope.datasetNames = ['DATASET1','DATASET2', 'DATASET3];
For figure b the reducing functions produce a structure like:
JSON.stringify( reducedGroup.all()[10] )
"{"key":2.6550000000000002,"value":{"sums":{"DATASET1":54.379999999999995,"DATASET2":43.38,"DATASET3":76.56000000000002},"counts":{"DATASET1":20,"DATASET2":16,"DATASET3":28},"dataset":"DATASET3","sampleid":"ID3225"}}"
The essential code for drawing the chart is below.
var createSVG = function( scope, element, dimension, reducedGroup, variable, noBins, extent, binWidth, colorMap ) {
scope.width = 470;
scope.height = 345;
scope.histogram = dc.barChart( element[0] );
scope.histogram
.width(scope.width)
.height(scope.height)
.xUnits( function() { return 20; } )
.margins({top: 15, right: 10, bottom: 20, left: 40})
.dimension(dimension);
_.each( scope.datasetNames, function(name,ind) {
if( ind === 0 )
{
scope.histogram
.group(reducedGroup, name)
.valueAccessor( function(d) {
if( _.isUndefined( d.value.dataset ) ) {
return 0;
}
return d.value.counts[name];
});
}
else {
scope.histogram
.stack( reducedGroup, name, function(d) {
if( _.isUndefined( d.value.dataset ) ) {
return 0;
}
return d.value.counts[name];
});
}
});
scope.histogram.round(Math.floor)
.centerBar(false)
.x(d3.scale.linear().domain(extent).range([0,noBins]))
.elasticY(true)
.brushOn(true)
.xAxis().ticks(7).tickFormat( d3.format(".2s") );
scope.histogram.render();
};
What exactly am I doing wrong here? Does this have to do something with keyAccessor function, which I currently don't have in the code? And why is there a double-width y-axis line on these charts?
The answer turned out to be rather simple. The code contained
.round(Math.floor)
which caused the brush filter problem. The double-width y-axis line remains a mystery.
Instead of rotating the camera with camera.rotation or with the lookAt() function
I'd like to pass a look vector directly to the camera... Is it possible to set a camera look vector directly and is it possible to read the look vector from the camera?
The camera does not have a "look vector", so you cannot set it.
You can, however, construct a point to look at by adding your look vector to the camera's position, and then calling
camera.lookAt( point );
Here is how to determine the direction in which the camera is looking, assuming the camera either has no parent (other than the scene).
The camera is looking down its internal negative z-axis, so create a vector pointing down the negative z-axis:
var vector = new THREE.Vector3( 0, 0, - 1 );
Now, apply the same rotation to the vector that is applied to the camera:
vector.applyQuaternion( camera.quaternion );
The resulting vector will be pointing in the direction that the camera is looking.
Alternatively, you can use the following method, which works even if the camera is a child of another object:
camera.getWorldDirection( dirVector );
three.js r.73
These other answers are very insightful, but not completely correct. The code returns a vector that points in the same direction that the camera is pointing at. That's a great start!
But unless the camera is at the origin (0, 0, 0) (or lies exactly on the line segment that connects the origin to the rotated vector point without passing beyond that point so that the point is behind the camera) the camera won't be looking at that point. Clearly -- just common sense -- the position of the camera also influences what points are being looked at. Just think about it!!
The camera method lookAt() looks at a point in 3D space regardless of where the camera is. So to get a point that the camera is looking at you need to adjust for the camera position by calling:
vec.add( camera.position );
It is also worth mentioning that the camera is looking not at a single point but is looking down a line of an infinite number of points, each at a different distance from the camera. The code from the other answers returns a vector that is exactly one unit in length because the application of a quaternion to the normalized z-axis vector (0, 0, -1) returns another normalized vector (in a different direction). To calculate the look at point at an arbitrary distance x from the camera use:
THREE.Vector3( 0, 0, -x ).applyQuaternion( camera.quaternion ).add( camera.position );
This takes a point along the z-axis at a distance x from the origin, rotates it to the direction of the camera and then creates a "world point" by adding the camera's position. We want a "world point" (and not just a "relative to the camera point") since camera.lookAt() also takes a "world point" as a parameter.
The above answer wrapped as a util, this is what I do with my Three Utils:
THREE.Utils = {
cameraLookDir: function(camera) {
var vector = new THREE.Vector3(0, 0, -1);
vector.applyEuler(camera.rotation, camera.eulerOrder);
return vector;
}
};
Call it with THREE.Utils.cameraLookDir(camera);
What I did was to use method lookAt(Vector) just before render the scene like in below code , just try it using it on a new html file :)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style >
*{
margin: 0 ;
}
#WebGlElement {
height: 500px;
width: 500px;
background-color: red
}
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<div id="WebGlElement"></div>
<script>
var contianer = document.getElementById("WebGlElement");
var origin = new THREE.Vector3(0,0,0);
// CREATE THREE BASIC ELEMENTS
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 40, 300/300, 1, 1000 );
var renderer = new THREE.WebGLRenderer();
// SET RENDERER AND ATTACH IT TO BODY
renderer.setSize( 500, 500 );
//document.body.appendChild( renderer.domElement );
contianer.appendChild( renderer.domElement);
// CREATE A GEOMETRY AND ADD IT TO SCENE
/*var geometry = new THREE.BoxGeometry( 1, 1, 5 );
var material = new THREE.MeshBasicMaterial( { color: 0x1abc9c } );
material.wireframe = true ;
material.wireframeLinewidth = 0.1 ;
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );*/
var geometry = new THREE.Geometry();
geometry.elementsNeedUpdate=true;
geometry.vertices.push(
new THREE.Vector3( -0, 1, 0 ),
new THREE.Vector3( -1, -1, 0 ),
new THREE.Vector3( 1, -1, 0 )
);
geometry.faces.push(
new THREE.Face3( 0, 1, 2 ),
new THREE.Face3( 2, 1, 0 )
);
var material = new THREE.MeshBasicMaterial( { color: 0x1abc9c } );
//material.wireframe = true ;
//material.wireframeLinewidth = 0.1 ;
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
var axisHelper = new THREE.AxisHelper( 1 );
scene.add( axisHelper );
// POSITION OF CAMER ON Z
camera.position.z = 5;
camera.position.y = 5;
camera.up = new THREE.Vector3(0,0,1);
var dir = 1;
var number = 0.115
// CREATE FUNCTION FOR RENDER
var render = function () {
requestAnimationFrame( render );
//circle.rotation.x += 0.01;
if ( camera.position.x> 5) {
dir = -1;
}
if ( camera.position.x< -5) {
dir = 1;
}
camera.lookAt(cube.position);
//camera.rotation.y += 0.015 * dir;
camera.position.x += number * dir;
renderer.render(scene, camera);
};
// EXECUTE FIRST RENDER
render();
</script>
</body>
</html>
I have an item renderer for a grid that has a fairly basic updateDisplayList function:
override protected function updateDisplayList( w : Number, h : Number ) : void
{
super.updateDisplayList( w, h );
var labelWidth : Number = Math.min( _labelDisplay.measuredWidth, w );
var labelHeight : Number = Math.min( _labelDisplay.measuredHeight, h );
_labelDisplay.setActualSize( labelWidth, labelHeight );
var labelX : Number = ( w - _labelDisplay.width ) / 2;
var labelY : Number = ( h - _labelDisplay.height ) / 2;
_labelDisplay.move( labelX, labelY );
//this is just for debugging
graphics.clear();
graphics.beginFill( 0xFF0000, 0.5 );
graphics.drawRect( labelX, labelY, labelWidth, labelHeight );
graphics.endFill();
}
where _labelDisplay is a spark label. When I scroll the grid (this is a cuatom grid, not mx:Grid or AndvancedDataGrid) when new rows appear at the bottom of the grid updateDisplayList is called and the code to re-draw the background and move / resize the label executes.
The problem is that these chanegs are not reflected in the view. The text is mis-aligned as a label that used to display a large string now displays a short string so the measuredWidth has changed.
The next time I scroll the renders update to look like they should - but updateDisplayList is NOT called here (on the renderes). All that happens is that the renderers are re-positioned in the grid.
Both the background and the label are displayed incorrectly initially so it's not just the label mis-behaving.
Anyone got any idea why this is happening?
Thanks
Just a guess, but does this make any difference?
override protected function updateDisplayList( w : Number, h : Number ) : void
{
var labelWidth : Number = Math.min( _labelDisplay.measuredWidth, w );
var labelHeight : Number = Math.min( _labelDisplay.measuredHeight, h );
_labelDisplay.setActualSize( labelWidth, labelHeight );
var labelX : Number = ( w - _labelDisplay.width ) / 2;
var labelY : Number = ( h - _labelDisplay.height ) / 2;
_labelDisplay.move( labelX, labelY );
super.updateDisplayList( w, h ); // Call updateDisplayList after moving / resizing _labelDisplay
}
I have write a simple example that adds a canvas and draw a rectangle with stroke size 20 scale mode none.
The problem is that if I call getBounds() first time I will get a correct result but after I call scale(); the getBounds() function will give me a wrong result.
It will take in cosideration the stroke but stroke has scalemode to none and on the screen nothing happens but in the result I will have a x value smaller. Can sombody tell me how can I fix this?
protected var display :Canvas;
protected function addCanvas():void
{
display = new Canvas();
display.x = display.y = 50;
display.width = 100;
display.height = 100;
display.graphics.clear();
display.graphics.lineStyle( 20, 0x000000, 0.5, true, LineScaleMode.NONE );
display.graphics.beginFill( 0xff0000, 1 );
display.graphics.drawRect(0, 0, 100, 100);
display.graphics.endFill();
area.addChild( display );
traceBounce();
}
protected function scale():void
{
var m :Matrix = display.transform.matrix;
var apply :Matrix = new Matrix();
apply.scale( 2, 1 );
apply.concat( m );
display.transform.matrix = apply;
traceBounce();
}
protected function traceBounce():void
{
trace( display.getBounds( this ) );
}
Setting the width/height and scaling the same display object can give confusing results. Does your Canvas class do anything unusual (e.g. set the scrollRect or add a mask)?
Also you could try getting bounds of the Canvas' parent instead, or setting cacheAsBitmap on the Canvas and seeing if that helps?