In MPAndroidChart, I can control the frequency of xaxis values with setSkipLabels. However, this only affects the xaxis. How do I do the same with the lines themselves in a line chart?
I don't think the library provide a neat way to do this for LineDataSet as for X axis.
The best bet IMHO should be to use a custom ValueFormatter to set text to blank as required.
Exemple to show one label out of ten:
public class MyValueFormatter implements ValueFormatter {
private DecimalFormat mFormat;
public MyValueFormatter() {
mFormat = new DecimalFormat("###,###,##0.0"); // use one decimal
}
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
String output = "";
if (entry.getXIndex() % 10 == 0) output = mFormat.format(value);
return output;
}
}
Then, attach your formatter to your DataSet
lineDataSet.setValueFormatter(new MyValueFormatter());
This will only affect text displayed next to each value in the graph.
You could also disable drawing the circle on each value with :
lineDataSet.setDrawCircles(false);
Related
I used a extended version of LocationTextExtractionStrategy to extract connected texts of a pdf and their positions/sizes. I did this by using the locationalResult. This worked well until I tested a pdf containing texts with a different font (ttf). Suddenly these texts are splitted into single characters or small fragments.
For example "Detail" is not any more one object within the locationalResult list but splitted into six items (D, e, t, a, i, l)
I tried using the HorizontalTextExtractionStrategy by making the getLocationalResult method public:
public List<TextChunk> GetLocationalResult()
{
return (List<TextChunk>)locationalResultField.GetValue(this);
}
and using the PdfReaderContentParser to extract the texts:
reader = new PdfReader("some_pdf");
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
var strategy = parser.ProcessContent(i, HorizontalTextExtractionStrategy());
foreach (HorizontalTextExtractionStrategy.HorizontalTextChunk chunk in strategy.GetLocationalResult())
{
// Do something with the chunk
}
but this also returns the same result.
Is there any other way to extract connected texts from a pdf?
I used a extended version of LocationTextExtractionStrategy to extract connected texts of a pdf and their positions/sizes. I did this by using the locationalResult. This worked well until I tested a pdf containing texts with a different font (ttf). Suddenly these texts are splitted into single characters or small fragments.
This problem is due to wrong expectations concerning the contents of the LocationTextExtractionStrategy.locationalResult private list member variable.
This list of TextChunk instances contains the pieces of text as they were forwarded to the strategy from the parsing framework (or probably as they were preprocessed by some filter class), and the framework forwards each single string it encounters in a content stream separately.
Thus, if a seemingly connected word in the content stream actually is drawn using multiple strings, you get multiple TextChunk instances for it.
There actually is some "intelligence" in the method getResultantText joining these chunks properly, adding a space where necessary and so on.
In case of your document, "DETAIL " usually is drawn like this:
[<0027> -0.2<00280037> 0.2<0024002c> 0.2<002f> -0.2<0003>] TJ
As you see there are slight text insertion point moves between 'D' and 'E', 'T' and 'A', 'I' and 'L', and 'L' and ' '. (Such mini moves usually represent kerning.) Thus, you'll get individual TextChunk instances for 'D', 'ET', 'AI', and 'L '.
Admittedly, the LocationTextExtractionStrategy.locationalResult member is not very well documented; but as it is a private member, this IMHO is forgivable.
That this worked well for many documents is due to many PDF creators not applying kerning and simply drawing connected text using single string objects.
The HorizontalTextExtractionStrategy is derived from the LocationTextExtractionStrategy and mainly differs from it in the way it arranges the TextChunk instances to a single string. Thus, you'll see the same fragmentation here.
Is there any other way to extract connected texts from a pdf?
If you want "connected texts" as in "atomic string objects in the content stream", you already have them.
If you want "connected texts" as in "visually connected texts, no matter where the constituent letters are drawn in the content stream", you have to glue those TextChunk instances together like the LocationTextExtractionStrategy and HorizontalTextExtractionStrategy do in getResultantText in combination with the comparison methods in their respective TextChunkLocationDefaultImp and HorizontalTextChunkLocation implementations.
After debugging deep into the iTextSharp library I figured out that my texts are drawn with the TJ operator as mkl also mentioned.
[<0027> -0.2<00280037> 0.2<0024002c> 0.2<002f> -0.2<0003>] TJ
iText processes these texts not as a single PdfString but as an array of PdfObjects which ends up in calling renderListener.RenderText(renderInfo) for each PdfString item in it (see ShowTextArray class and DisplayPdfString method). In the RenderText method however the information about the relation of the pdf strings within the array got lost and every item is added to locationalResult as an independent object.
As my goal is to extract the "argument of a single text drawing instruction" I extended the PdfContentStreamProcessor class about a new method ProcessTexts which returns a list of these atomic strings. My workaround is not very pretty as I had to copy paste some private fields and methods from the original source but it works for me.
class PdfContentStreamProcessorEx : PdfContentStreamProcessor
{
private IDictionary<int, CMapAwareDocumentFont> cachedFonts = new Dictionary<int, CMapAwareDocumentFont>();
private ResourceDictionary resources = new ResourceDictionary();
private CMapAwareDocumentFont font = null;
public PdfContentStreamProcessorEx(IRenderListener renderListener) : base(renderListener)
{
}
public List<string> ProcessTexts(byte[] contentBytes, PdfDictionary resources)
{
this.resources.Push(resources);
var texts = new List<string>();
PRTokeniser tokeniser = new PRTokeniser(new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateSource(contentBytes)));
PdfContentParser ps = new PdfContentParser(tokeniser);
List<PdfObject> operands = new List<PdfObject>();
while (ps.Parse(operands).Count > 0)
{
PdfLiteral oper = (PdfLiteral)operands[operands.Count - 1];
if ("Tj".Equals(oper.ToString()))
{
texts.Add(getText((PdfString)operands[0]));
}
else if ("TJ".Equals(oper.ToString()))
{
string text = string.Empty;
foreach (PdfObject entryObj in (PdfArray)operands[0])
{
if (entryObj is PdfString)
{
text += getText((PdfString)entryObj);
}
}
texts.Add(text);
}
else if ("Tf".Equals(oper.ToString()))
{
PdfName fontResourceName = (PdfName)operands[0];
float size = ((PdfNumber)operands[1]).FloatValue;
PdfDictionary fontsDictionary = resources.GetAsDict(PdfName.FONT);
CMapAwareDocumentFont _font;
PdfObject fontObject = fontsDictionary.Get(fontResourceName);
if (fontObject is PdfDictionary)
_font = GetFont((PdfDictionary)fontObject);
else
_font = GetFont((PRIndirectReference)fontObject);
font = _font;
}
}
this.resources.Pop();
return texts;
}
string getText(PdfString #in)
{
byte[] bytes = #in.GetBytes();
return font.Decode(bytes, 0, bytes.Length);
}
private CMapAwareDocumentFont GetFont(PRIndirectReference ind)
{
CMapAwareDocumentFont font;
cachedFonts.TryGetValue(ind.Number, out font);
if (font == null)
{
font = new CMapAwareDocumentFont(ind);
cachedFonts[ind.Number] = font;
}
return font;
}
private CMapAwareDocumentFont GetFont(PdfDictionary fontResource)
{
return new CMapAwareDocumentFont(fontResource);
}
private class ResourceDictionary : PdfDictionary
{
private IList<PdfDictionary> resourcesStack = new List<PdfDictionary>();
virtual public void Push(PdfDictionary resources)
{
resourcesStack.Add(resources);
}
virtual public void Pop()
{
resourcesStack.RemoveAt(resourcesStack.Count - 1);
}
public override PdfObject GetDirectObject(PdfName key)
{
for (int i = resourcesStack.Count - 1; i >= 0; i--)
{
PdfDictionary subResource = resourcesStack[i];
if (subResource != null)
{
PdfObject obj = subResource.GetDirectObject(key);
if (obj != null) return obj;
}
}
return base.GetDirectObject(key); // shouldn't be necessary, but just in case we've done something crazy
}
}
}
I'm using the following code to add checkbox field to an existing PDF. Note the code is in C#, so might be a little different than in iText, but should share the same concept.
private void addCheckboxField( PdfStamper stamper, iTextSharp.text.Rectangle rect, String name, int pagenumber, bool isChecked)
{
RadioCheckField field = new RadioCheckField(stamper.Writer, rect, name, "Yes");
field.CheckType = RadioCheckField.TYPE_CHECK;
field.Checked = isChecked;
field.BorderWidth = BaseField.BORDER_WIDTH_THIN;
field.BorderColor= BaseColor.BLACK;
field.BackgroundColor = BaseColor.WHITE;
stamper.AddAnnotation(field.CheckField, pagenumber);
}
Then I call this function to generate a checkbox in desired position of an existing PDF. Problem is the checkbox is not checked when passing true. Also the field is editable.
How can I check it and how can I make it readonly.
Okay, I get that resolved. field.Options+=RadioCheckField.READ_ONLY;
As it is a first time I'm using ArrayList in Processing I'm experiencing some issues.
I have created an Arraylist that stores a PVector (x,y position) of an Ellipsee.
What I'm trying to do is very simple I think but I can't find much info on ArrayLists.
Code:
ArrayList position;
void setup()
{
position= new ArrayList<Vectors>();
}
void draw()
{
position.get(i).display(); //display ellipse
}
void mousePressed()
{
position.add(new Vectors(new PVector(mouseX, mouseY)));
}
So every time mouse is Pressed a new ellipse is created at mouseX mouseY position. What I would like to do is when my I created an amount ellipses, I need to control each one separately to change it's size or color either by clicking on them or with KeyPressed().
This won't compile automatically as I'm assuming your PVector object has already been created and that it has two public attributes of xPosition and yPosition:
// Initialise your arraylist
ArrayList<PVector> listOfPVectors = new ArrayList<PVector>;
// Objects can be added to your list as follows:
PVector pvectorObject = new PVector();
listOfPVectors.add(pvectorObject);
// The size of your ArrayList can be output as follows:
println(listOfPVectors.size());
// You can iterate through every entry in the arraylist as follows:
for(int index = 0; index < listOfPVectors.size(); index ++) {
println("X Position Value = " + listOfPVectors.get(index).xPosition);
println("Y Position Value = " + listOfPVectors.get(index).yPosition);
}
Basically, you use the ArrayList.get(indexPosition) method to retrieve any element you want from your ArrayList. You can then work away with it as normal.
Hope this helps!
I am trying to customize the series labels of the X axis of a linear ultrachart using vb.net.
I looked into the documentation from Infragistics and found that I could use this code:
UltraChart.Axis.Y.Labels.SeriesLabels.FormatString = "<Item_Label>"
A description of the types of labels available can be seen here.
However, I'm not getting the result I expected. I get "Row#1" and I want to get only the "1".
I've tried the approach used in the first reply of this post in Infragistics forums, which consists of using an hashtable with the customized labels. The code used there is the following (in C#):
Hashtable labelHash = new Hashtable();
labelHash.Add("CUSTOM", new MyLabelRenderer());
ultraChart1.LabelHash = labelHash;
xAxis.Labels.ItemFormatString = "<CUSTOM>";
public class MyLabelRenderer : IRenderLabel
{
public string ToString(Hashtable context)
{
string label = (string)context["ITEM_LABEL"];
int row = (int)context["DATA_ROW"];
int col = (int)context["DATA_COLUMN"];
//use row, col, current label's text or other info inside the context to get the axis label.
//the string returned here will replace the current label.
return label;
}
}
This approach didn't work either.
I am using Infragistics NetAdvantage 2011.1.
Anyone has any idea how to customize these labels in order to obtain the number after "Row#"?
There are different approaches to solve this task. One possible solution could be if you are using FillSceneGraph event. By this way you could get your TEXT primitives and modify it. For example:
private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e)
{
foreach (Primitive pr in e.SceneGraph)
{
if (pr is Text &&((Text)pr).labelStyle.Orientation == TextOrientation.VerticalLeftFacing )
{
pr.PE.Fill = Color.Red;
((Text)pr).SetTextString("My custom labels");
}
}
}
OK. I`ll try to explain more deeply about FormatString property.
When you are using this property, you could determinate which information to be shown (for example: Items values or Data Values or Series Values). Of course there are option to use your custom FormatString.
For example:
axisX2.Labels.ItemFormat=AxisItemLabelFormat.Custom;
axisX2.Labels.ItemFormatString ="";
In this case we have labels which represent Date on your X axis, so if you are using these two properties, you are able to determinate the Date format (for example dd/MM/yyyy or MM/ddd/yy). In your scenario you have string values on your X axis. If you are not able to modify these strings values at lower level (for example in your database, through TableAdapters SQL query, DataSet, i.e. before to set your DataSource to our UltraChart), then you could use FillSceneGraph event and modify your Text primitives. More details about this event you could find at http://help.infragistics.com/Help/NetAdvantage/WinForms/2013.1/CLR4.0/html/Chart_Modify_Scene_Graph_Using_FillSceneGraph_Event.html If you need a sample or additional assistance, please do not hesitate to create a new forum thread in our web site - http://www.infragistics.com/community/forums/
I`ll be glad to help you.
I'm ramping up on a Silverlight 2 project that leverages the Bing Maps control. One thing our UX guys are wondering is whether it is possible to customize the look of the map completely. For example, draw countries as simple outlines with different color interiors. Or draw the ocean as white and countries as black dotted shapes.
Does anyone know whether it is possible to achieve this level of customization? The MapMode class looked promising, but it doesn't seem to quite give me what I need.
Thanks,
Kent
To answer my own question, yes this is possible.
Firstly, add your own layer with a custom tile source:
<m:Map>
<m:Map.Mode>
<mCore:MercatorMode/>
</m:Map.Mode>
<m:Map.Children>
<m:MapTileLayer>
<m:MapTileLayer.TileSources>
<local:CustomTileSource/>
</m:MapTileLayer.TileSources>
</m:MapTileLayer>
</m:Map.Children>
</m:Map>
Next, define the CustomTileSource. Here is an example:
public class CustomTileSource : TileSource
{
public CustomTileSource()
: base(GetAbsoluteUrl("/ClientBin/Resources/{0}.png"))
{
}
public override Uri GetUri(int x, int y, int zoomLevel)
{
var quadKey = new QuadKey(x, y, zoomLevel);
return new Uri(String.Format(this.UriFormat, quadKey.Key));
}
public static string GetAbsoluteUrl(string strRelativePath)
{
if (string.IsNullOrEmpty(strRelativePath))
return strRelativePath;
string strFullUrl;
if (strRelativePath.StartsWith("http:", StringComparison.OrdinalIgnoreCase)
|| strRelativePath.StartsWith("https:", StringComparison.OrdinalIgnoreCase)
|| strRelativePath.StartsWith("file:", StringComparison.OrdinalIgnoreCase)
)
{
//already absolute
strFullUrl = strRelativePath;
}
else
{
//relative, need to convert to absolute
strFullUrl = System.Windows.Application.Current.Host.Source.AbsoluteUri;
if (strFullUrl.IndexOf("/ClientBin") > 0)
strFullUrl = strFullUrl.Substring(0, strFullUrl.IndexOf("/ClientBin")) + strRelativePath;
}
return strFullUrl;
}
}
Note how the tile source must return a URL. If you have an image you want to use as the map, you can use the MapCruncher tool to prepare it.