I am trying to implement a chart with a ColumnRenderableSeries3D series, but with a small amount of data points (25x25) the columns are nearly invisible. At higher numbers of data points (100x100) with a wider range of values this problem becomes even worse and a Moiré pattern appears. What can be done to significantly increase the column's diameter, so they are easily seen and so the Moiré pattern disappears?
If it is relevant this is being rendered on a VM with a VMware ESXi 6.5 SVGA adapter on Windows Server 2016, over a RemoteDesktop connection. Surprisingly even though 3D support isnt enabled for the VM, SciChart.Examples.Demo.exe says DirectX hardware acceleration is enabled. The version of SciChart is 5.1.0.11405 and SharpDX is 4.0.1.
SciChart3DSurface SciChartSurface3d = new SciChart3DSurface();
XyzDataSeries3D<Double, Double, DateTime> MyXyzDataSeries = new XyzDataSeries3D<Double, Double, DateTime>();
SciChartSurface3d.XAxis = new NumericAxis3D();
SciChartSurface3d.YAxis = new NumericAxis3D();
SciChartSurface3d.ZAxis = new DateTimeAxis3D();
SciChartSurface3d.Camera = new Camera3D() { ZoomToFitOnAttach = true };
SciChartSurface3d.WorldDimensions = new Vector3(200, 100, 200);
SciChartSurface3d.RenderableSeries.Add(new ColumnRenderableSeries3D() { DataSeries= MyXyzDataSeries, ColumnShape = typeof(CubePointMarker3D), DataPointWidthX = 1.0, Opacity = 1.0 });
SciChartSurface3d.BorderThickness = new Thickness(0);`
SomeMethodToLoadTheDataSeries();
25x25
100x100
Edit
Changing DataPointWidthX to DataPointWidth doesn't help. With a width of 1.0:
There are two modes of the column width definition:
First and the default is called MaxNonOverlapping. In this mode, the maximum possible width is calculated where any column has enough space not to overlap others.
Second is called FixedSize. In this mode, the width of a column is defined by a value from the ColumnRenderableSeries3D.CoulmnFixedSize property.
Definition of the mode is performed over the ColumnRenderableSeries3D.ColumnSpacingMode property. Below is the example how to setup fixed size column chart:
var renderableSeries3D = new ColumnRenderableSeries3D();
renderableSeries3D.ColumnSpacingMode = ColumnSpacingMode.FixedSize;
renderableSeries3D.CoulmnFixedSize = 25;
Note, a value of the CoulmnFixedSize property represents coordinates space. Thus it is related to the SciChart3DSurface.WorldDimensions. You can find more information about the coordinates space here.
Related
Every value I set for .scale() lower than 0.01 will be handled as I set 0.01, rendering a text that is not lower than when I set it to 0.01.
FreetypeFontLoader.FreeTypeFontLoaderParameter sizeParams = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
sizeParams.fontFileName = "MyFont.ttf";
sizeParams.fontParameters.size = (int)Math.ceil(2*MINIMUM_VIEWPORT_SIZE_PIXEL/9f/2f/2f);
sizeParams.fontParameters.color = new Color(Color.Red);
sizeParams.fontParameters.borderColor = new Color(Color.Green);
sizeParams.fontParameters.borderWidth = 2;
sizeParams.fontParameters.minFilter = Texture.TextureFilter.Linear;
sizeParams.fontParameters.magFilter = Texture.TextureFilter.Linear;
assetManager.load("MyFont.ttf", BitmapFont.class, sizeParams);
assetManager.finishLoading();
BitmapFont fontFreeType = assetManager.get("myFont.ttf", BitmapFont.class);
Label.LabelStyle miniLabelStyle = new Label.LabelStyle();
miniLabelStyle.font = fontFreeType;
miniLabelStyle.font.getData().scale(0.005f);
Label labelDebug = new Label("my sample text", game.miniLabelStyle);
I tried this, without any change (either setting true or false):
miniLabelStyle.font.setUseIntegerPositions(false);
I tried this, but the text results so grainy:
labelDebug.setFontScale(0.5f);
How to get a lower scale than 0.01?
This is just a guess, since I don't use FreetypeFontGenerator, but maybe what you're missing is mip mapping, which is necessary for drawing images smaller than their original size without them getting blurry and chunky.
You'll want to make these two settings to enable it, I think:
sizeParams.fontParameters.minFilter = Texture.TextureFilter.MipMapLinearLinear;
sizeParams.fontParameters.genMipMaps = true;
You might also need to add padding around the glyphs so characters don't absorb some of their neighbors when shrunk down. (Settings padTop, padLeft, padBottom, padRight.)
However, there's a reason mip mapping defaults to being disabled. Text looks clearest if it's generated at exactly the size it will be on screen and is rendered with nearest filtering. This isn't universally true, since you might be projecting your text in 3D space or scaling it up and down in real-time. But if it's static text for a GUI, it's probably best to calculate exactly what size it would need to be for it to be one-texture-pixel to one-screen-pixel.
A potential problem I noticed in SciChart for WPF
take the standard example for ColumnChart from SDK (2D Charts - Column Chart)
build and run; the result is as below:
make the following code changes (see (1) and (2))
private void ColumnChartExampleViewOnLoaded(object sender, RoutedEventArgs e)
{
var dataSeries = new XyDataSeries<double, double> {SeriesName = "Histogram"};
var yValues = new double[] { 0.1, 0.2, 0.4, 0.8, 1.1, 1.5, 2.4, 4.6, 8.1, 11.7, 14.4, 16.0, 13.7, 10.1, 6.4, 3.5, 2.5, 1.4, 0.4, 0.1};
using (this.sciChart.SuspendUpdates())
{
for (int i = 0; i < yValues.Length; i++)
{
// DataSeries for appending data
dataSeries.Append(i, yValues[i]);
}
this.columnSeries.DataSeries = dataSeries;
this.columnSeries.DataSeries.AcceptsUnsortedData = true; //(1)
}
dataSeries.Append(0, 1); //(2)
this.sciChart.ZoomExtents();
}
and here is the result:
I.e. if I use Append method for the X val which already exists - the UI bars are changing to the lines.
I do not know if it is expected behavior or not but for my case I'm updating the Histogram on fly and quite often same X value is having new Y value(s).
As a result - the UI behavior confuses...
I found workaround for my case (I'm using the Update method since X and index is the same for my case) so this is just a notice.
I'm not sure will you change the behavior or not - just sharing my experience for now...
SciChart's column series automatically calculates the width of the data-points based on the columns you have available.
If you have columns 0,1,2,3,4,5,6,7,8,9 ...then add a new column at position 0, this calculation goes haywire.
Ways of avoiding this side-effect are:
Update items rather than append new columns with overlapping values
Override column width calculation using the properties FastColumnRenderableSeries.UseUniformWidth and FastColumnRenderableSeries.DataPointWidth
(Advanced) Override column width calculation by overriding GetDataPointWidth() method.
Find out more how the Column series works at the SciChart WPF Documentation page.
I am working with Google earth Engine and I am trying to extract/Filter (clip) pixels in a band using another image (band). I calculated NDVI and created a threshold value that rendered an image with NDVI > 0.3 but I wanted to extract the corresponding pixels in the visible an NIR bands.
Here is snippet code.
var s2 = ee.ImageCollection('COPERNICUS/S2');
var s2_filtered = s2.filterDate('2017-01-01', '2017-12-31')
.filterBounds(geometry) //custom Geometry
var calcNDVI = function(x){
var ndvi4 = x.normalizedDifference(["B5", "B4"]).rename("ndvi")
return x.addBands(ndvi)
}
var ndviCollection = s2_filtered.map(calcNDVI)
var maxNDVI = mosaic.select("ndvi");
var threshold = maxNDVI.gt(0.3)
I am at the point where I wanted to clip the corresponding pixels in "B", "G", "R" and "NIR" bands using the threshold variable(image). Obviously, I'm stuck here. Please let me know if there is with a way to filter/clip pixels of one band using another band with in GEE. The task is similar to using Clipper in QGIS which is the options I am left with if this doesn't work.
Thanks for your help!
The variable threshold is a mask, so you have to mask out pixels in the mosaic using the threshold mask, right? If that is the case, simply update the mask of the image:
var masked = maxNDVI.updateMask(threshold)
I am using graphhopper 0.8 via maven in my java project. I create a network with the folling code
FlagEncoder encoder = new CarFlagEncoder();
EncodingManager em = new EncodingManager(encoder);
// Creating and saving the graph
GraphBuilder gb = new GraphBuilder(em).
setLocation(testDir).
setStore(true).
setCHGraph(new FastestWeighting(encoder));
GraphHopperStorage graph = gb.create();
for (Node node : ALL NODES OF MY NETWORK) {
graph.getNodeAccess().setNode(uniqueNodeId, nodeX, nodeY);
}
for (Link link : ALL LINKS OF MY NETWORK) {
EdgeIteratorState edge = graph.edge(fromNodeId, toNodeId);
edge.setDistance(linkLength);
edge.setFlags(encoder.setProperties(linkSpeedInMeterPerSecond * 3.6, true, false));
}
Weighting weighting = new FastestWeighting(encoder);
PrepareContractionHierarchies pch = new PrepareContractionHierarchies(graph.getDirectory(), graph, graph.getGraph(CHGraph.class), weighting, TraversalMode.NODE_BASED);
pch.doWork();
graph.flush();
LocationIndex index = new LocationIndexTree(graph.getBaseGraph(), graph.getDirectory());
index.prepareIndex();
index.flush();
At this point, the bounding box saved in the graph shows the correct numbers. Files are written to disk including the "location_index". However, reloading the data gets me the following error
Exception in thread "main" java.lang.IllegalStateException: Cannot create location index when graph has invalid bounds: 1.7976931348623157E308,1.7976931348623157E308,1.7976931348623157E308,1.7976931348623157E308
at com.graphhopper.storage.index.LocationIndexTree.prepareAlgo(LocationIndexTree.java:132)
at com.graphhopper.storage.index.LocationIndexTree.prepareIndex(LocationIndexTree.java:287)
The reading is done with the following code
FlagEncoder encoder = new CarFlagEncoder();
EncodingManager em = new EncodingManager(encoder);
GraphBuilder gb = new GraphBuilder(em).
setLocation(testDir).
setStore(true).
setCHGraph(new FastestWeighting(encoder));
// Load and use the graph
GraphHopperStorage graph = gb.load();
// Load the index
LocationIndex index = new LocationIndexTree(graph.getBaseGraph(), graph.getDirectory());
if (!index.loadExisting()) {
index.prepareIndex();
}
So LocationIndexTree.loadExisting runs fine until entering prepareAlgo. At this point, the graph is loaded. However, the bounding box is not set and kept at the defaults?! Reading the location index does not update the bounding box. Hence, the error downstreams. What am I doing wrong? How do I preserve the bounding box in the first place? How to reconstruct the bbox?
TL;DR Don't use cartesian coordinates but stick to the WGS84 used by OSM.
A cartesian coordinate system like e.g. EPSG:25832 may have coordinates in the range of millions. After performing some math the coordinates may further increase in magnitude. Eventually, Graphhopper will store the coordinates as integers. That is, all coordinates may end up as Integer.MAX_VALUE. Hence, an invalid bounding box.
I'm learning ActionScript/Flash. I love to play with text, and have done a lot of that kind of thing with the superb Java2D API.
One of the things I like to know is "where, exactly, are you drawing that glyph?" The TextField class provides the methods getBounds and getCharBoundaries, but these methods return rectangles that extend far beyond the actual bounds of the whole text object or the individual character, respectively.
var b:Sprite = new Sprite();
b.graphics.lineStyle(1,0xFF0000);
var r:Rectangle = text.getCharBoundaries(4);
r.offset(text.x, text.y);
b.graphics.drawRect(r.x,r.y,r.width,r.height);
addChild(b);
b = new Sprite();
b.graphics.lineStyle(1,0x00FF00);
r = text.getBounds(this);
b.graphics.drawRect(r.x,r.y,r.width,r.height);
addChild(b);
Is there any way to get more precise information about the actual visual bounds of text glyphs in ActionScript?
Richard is on the right track, but BitmapData.getColorBounds() is much faster and accurate... I've used it a couple of times, and optimized for your specific needs its not as slow as one might think.
Cory's suggestion of using flash.text.engine is probably the "correct" way to go, but I warn you that flash.text.engine is VERY (very!) hard to use compared to TextField.
Not reasonably possible in Flash 9 -- Richard's answer is a clever work-around, though probably completely unsuitable for production code (as he mentions) :)
If you have access to Flash 10, check out the new text engine classes, particularly TextLine.
I'm afraid all the methods that are available on TextField are supposed to do what you have already found them to do. Unless performance is key in your application (i.e. unless you intend to do this very often) maybe one option would be to draw the text field to a BitmapData, and find the topmost, leftmost, et c colored pixels within the bounding box retrieved by getCharBoundaries()?
var i : int;
var rect : Rectangle;
var top_left : Point;
var btm_right : Point;
var bmp : BitmapData = new BitmapData(tf.width, tf.height, false, 0xffffff);
bmp.draw(tf);
rect = tf.getCharBoundaries(4);
top_left = new Point(Infinity, Infinity);
btm_right = new Point(-Infinity, -Infinity);
for (i=rect.x; i<rect.right; i++) {
var j : int;
for (j=rect.y; j<rect.bottom; j++) {
var px : uint = bmp.getPixel(i, j);
// Check if pixel is black, i.e. belongs to glyph, and if so, whether it
// extends the previous bounds
if (px == 0) {
top_left.x = Math.min(top_left.x, i);
top_left.y = Math.min(top_left.y, j);
btm_right.x = Math.max(btm_right.x, i);
btm_right.y = Math.max(btm_right.y, j);
}
}
}
var actualRect : Rectangle = new Rectangle(top_left.x, top_left.y);
actualRect.width = btm_right.x - top_left.x;
actualRect.height = btm_right.y - top_left.y;
This code should loop through all the pixels that were deemed part of the glyph rectangle by getCharBoundaries(). If a pixel is not black, it gets discarded. If black, the code checks whether the pixels extends further up, down, right or left than any pixel that has previuosly been checked in the loop.
Obviously, this is not optimal code, with nested loops and unnecessary point objects. Hopefully though, the code is readable enough, and you are able to make out the parts that can most easily be optimized.
You might also want to introduce some threshold value instead of ignoring any pixel that is not pitch black.