In my project I have a method that draws a route inside of map and create a bounds for this route, the problem is, I need to create this bounds with the bottom sheet and not the entire screen!
First I open the Bottom Sheet:
private void openBottom(){
if(latLngs != null){
if(bottomSheetBehavior.getState() != BottomSheetBehavior.STATE_EXPANDED){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
bottomSheetBehavior.setPeekHeight(300);
}
}
}
And then Draw and the bounds!
private void drawnNewRoute() {
if(polyline == null){
LatLngBounds.Builder builder = new LatLngBounds.Builder();
po = new PolylineOptions();
for(int i = 0, tam = latLngs.size(); i < tam; i++){
po.add(latLngs.get(i));
builder.include(latLngs.get(i));
}
String data = new Gson().toJson(latLngs);
po.color(Color.BLACK).width(10);
polyline = mMap.addPolyline(po);
ArrayList<LatLng> latlang = new ArrayList<>();
latlang.add(latLngs.get(0));
latlang.add(latLngs.get(latLngs.size() -1));
mMarkerNewPosition = mMap.addMarker(new MarkerOptions().position(finalLocaltion).title(finalLocationName));
mMarkerNewPosition.showInfoWindow();
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 120));
location_display_incl.setVisibility(View.GONE);
stopLocation();
InicialAddressTxt.setText(InicialAddress);
double finalLat = latLngs.get(latLngs.size() -1).latitude;
double finalLong = latLngs.get(latLngs.size() -1).longitude;
try {
ADRS = getAddress(finalLat,finalLong);
} catch (IOException e) {
e.printStackTrace();
}
FinalAddressTxt.setText(finalLocationName);
String finalComp = ADRS.getLocality() + "," + address.getAdminArea();
FinalComplement.setText(finalComp);
//zoomToCoverAllMarkersInMap(latlang);
}
else{
polyline.setPoints(latLngs);
}
}
But it keeps getting the whole screen and not just the "available" part of it!
Related
Using PDFBox, given data notated like this: [G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,, I am creating a guitar chord sheet like this:
My approach was to iterate through each character in the song and check the current index against the map.. whenever the map has an entry to that character index, we "jump" to the line above, write the chord, then jump back down.
The method setTextRise looked promising, but still processes the horizontal spacing incorrectly:
Here's an SSCCE (needs PDFBox libraries) that produces the PDF above:
public static void main(String[] args) {
try {
String extracted_text = "Capo 1\n\n1\n[G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,\n[B7]Glory to the [Em]Holy [C]Spirit—\n[D-D7]Ever [ G]One.\n\n2\nAs we view the vast creation,\nPlanned with wondrous skill,\nSo our hearts would move to worship,\nAnd be still.\n\n3\nBut, our God, how great Thy yearning\nTo have sons who love\nIn the Son e’en now to praise Thee,\nLove to prove!\n\n4\n’Twas Thy thought in revelation,\nTo present to men\nSecrets of Thine own affections,\nTheirs to win.\n\n5\nSo in Christ, through His redemption\n(Vanquished evil powers!)\nThou hast brought, in new creation,\nWorshippers!\n\n6\nGlory be to God the Father,\nAnd to Christ the Son,\nGlory to the Holy Spirit—\nEver One.\n".replaceAll("\n", "\r");
String[] lines = extracted_text.split("\\r");
ArrayList<SongLine> songlines = new ArrayList<>();
for(String s : lines) {
LinkedHashMap<Integer, String> chords = new LinkedHashMap();
StringBuilder line = new StringBuilder();
StringBuilder currentchord = null;
int index = 0;
for(char c : s.toCharArray()) {
if(currentchord != null) {
if(c == ']') {
chords.put(index, currentchord.toString());
currentchord = null;
} else {
currentchord.append(c);
}
} else {
if(c == '[') {
currentchord = new StringBuilder();
} else {
line.append(c);
index++;
}
}
}
SongLine sl = new SongLine();
if(chords.size() > 0)
sl.char_index_to_chords = chords;
sl.line = line.toString();
songlines.add(sl);
}
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage();
PDPageContentStream pcs = new PDPageContentStream(doc, page);
int firstLineX = 25;
int firstLineY = 700;
boolean first = true;
float leading = 14.5f;
pcs.beginText();
pcs.newLineAtOffset(firstLineX, firstLineY);
pcs.setFont(PDType1Font.TIMES_ROMAN, 12);
pcs.setLeading(leading);
for(SongLine line : songlines) {
if(line.char_index_to_chords != null)
System.out.println(line.char_index_to_chords.toString());
System.out.println(line.line);
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
pcs.newLine();
}
for(int i = 0; i < line.line.length(); i++) {
pcs.showText(String.valueOf(line.line.charAt(i)));
if(line.char_index_to_chords != null && line.char_index_to_chords.containsKey(i)) {
pcs.setTextRise(12);
pcs.showText(line.char_index_to_chords.get(i));
pcs.setTextRise(0);
}
}
}
pcs.endText();
pcs.close();
doc.addPage(page);
String path = "0001.pdf";
doc.save(path);
Desktop.getDesktop().open(new File(path));
}
} catch (Exception e) {
e.printStackTrace();
}
}
static class SongLine {
Map<Integer, String> char_index_to_chords;
String line;
}
What would you do in PDFBox to create the text aligned with chords (like in the first image)?
I got it. The answer was not setTextRise, rather newLineAtOffset while using getStringWidth to calculate font size:
for(SongLine line : songlines) {
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
float offset = 0;
for(Entry<Integer, String> entry : line.char_index_to_chords.entrySet()) {
float offsetX = font.getStringWidth(line.char_index_to_leading_lyrics.get(entry.getKey())) / (float)1000 * fontSize;
pcs.newLineAtOffset(offsetX, 0);
offset += offsetX;
pcs.showText(entry.getValue());
}
pcs.newLineAtOffset(-offset, -leading);
}
pcs.showText(line.line);
}
I am using MPAndroid Library to create pie chart in my app, i am able take user input and display in pie chart but when user enter same value which is already in pie chart it won't displayed in pie chart and again when i enter different value, the previous value which i entered but didn't displayed will display in pie chart.
Any help will be appreciated !! Thank You.
Below is my pieChart method:
public void pieChart() {
mydb = new DBHelper(this);
try {
//Check for table in database
if (mydb.checkForTables())
{
stringItems.addAll(mydb.getAllItem());
intItems.addAll(mydb.getAllAmount());
} else {
Toast.makeText(this, "Data table is empty.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
List<Entry> yVals1 = new ArrayList<Entry>();
if(intItems.size() > 0)
{
for (int i = 0; i < intItems.size(); i++)
yVals1.add(new Entry(intItems.get(i), i));
}
else {
Toast.makeText(this,"intItem is empty !!",Toast.LENGTH_LONG).show();
}
List<String> xVals = new ArrayList<String>();
if(stringItems.size() > 0)
{
for (int i = 0; i < stringItems.size(); i++)
xVals.add(stringItems.get(i));
}else {
Toast.makeText(this,"stringItem is empty !!",Toast.LENGTH_LONG).show();
}
// create pieDataSet
PieDataSet dataSet = new PieDataSet(yVals1, " ");
dataSet.setSliceSpace(3);
dataSet.setSelectionShift(5);
// adding colors
List<Integer> colors = new ArrayList<Integer>();
// Added My Own colors
for (int c : MY_COLORS)
colors.add(c);
dataSet.setColors(colors);
// create pie data object and set xValues and yValues and set it to the pieChart
PieData data = new PieData(xVals, dataSet);
// data.setValueFormatter(new DefaultValueFormatter());
// data.setValueFormatter(new PercentFormatter());
data.setValueFormatter(new MyValueFormatter());
data.setValueTextSize(10f);
data.setValueTextColor(Color.WHITE);
mChart.setData(data);
// undo all highlights
mChart.highlightValues(null);
// refresh/update pie chart
mChart.invalidate();
// animate piechart
mChart.animateXY(1400, 1400);
// Legends to show on bottom of the graph
Legend l = mChart.getLegend();
l.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
l.setXEntrySpace(7);
l.setYEntrySpace(5);
}
private SpannableString generateCenterSpannableText() {
SpannableString s = new SpannableString("Overview");
s.setSpan(new RelativeSizeSpan(1.7f), 0, 8, 0);
s.setSpan(new StyleSpan(Typeface.NORMAL), 8, s.length(), 0);
return s;
}
public class MyValueFormatter implements ValueFormatter {
private DecimalFormat mFormat;
public MyValueFormatter() {
mFormat = new DecimalFormat("###,###,##0"); // use one decimal if needed
}
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
// write your logic here
return mFormat.format(value) + ""; // e.g. append a dollar-sign
}
}
I am trying to combign tiff image and shapefile and want show it. For this, I am using GeoTiff and I am stuck that my tiff file is now being displayed. Shapefile is showing properly but tiff image, which is having only 1 band and grey scale index, is not being shown because of some reason. I am getting one warning message as below.
2016-08-04T12:43:06.456+0530 WARNING Possible use of "Transverse_Mercator" projection outside its valid area.
Latitude 180°00.0'S is out of range (±90°).
How can I remove this message?
My code is as below
private void displayLayers() throws Exception {
AbstractGridFormat format = GridFormatFinder.findFormat(this.getBlueMarble());
this.setGridCoverageReader(format.getReader(this.getBlueMarble()));
Style rgbStyle = this.createRGBStyle();
// connect to the shapefile
FileDataStore dataStore = FileDataStoreFinder.getDataStore(this.getBorderShape());
SimpleFeatureSource shapefileSource = dataStore.getFeatureSource();
Style shpStyle = SLD.createPolygonStyle(Color.BLUE, null, 0.0f);
MapContent map = new MapContent();
map.getViewport().setCoordinateReferenceSystem(
DefaultGeographicCRS.WGS84);
map.setTitle("Illegal Mining");
Layer rasterLayer = new GridReaderLayer(this.getGridCoverageReader(), rgbStyle);
map.addLayer(rasterLayer);
Layer shpLayer = new FeatureLayer(shapefileSource, shpStyle);
map.addLayer(shpLayer);
System.out.println("Trying to show on map...");
JMapPane mapPane = new JMapPane();
mapPane.setMapContent(map);
mapPane.setDisplayArea(shapefileSource.getBounds());
//mapPane.setDisplayArea(this.getGridCoverageReader().getOriginalEnvelope());
this.add(mapPane, BorderLayout.CENTER);
}
private Style createRGBStyle() {
GridCoverage2DReader reader = this.getGridCoverageReader();
StyleFactory sf = this.getStyleFactory();
GridCoverage2D cov = null;
try {
cov = reader.read(null);
} catch (IOException giveUp) {
throw new RuntimeException(giveUp);
}
// We need at least three bands to create an RGB style
int numBands = cov.getNumSampleDimensions();
System.out.println("numBands:"+numBands);
if (numBands < 3) {
System.out.println("Bands are less than 3");
//return null;
}
// Get the names of the bands
String[] sampleDimensionNames = new String[numBands];
for (int i = 0; i < numBands; i++) {
GridSampleDimension dim = cov.getSampleDimension(i);
sampleDimensionNames[i] = dim.getDescription().toString();
}
final int RED = 0, GREEN = 1, BLUE = 2;
int[] channelNum = { -1, -1, -1 };
Boolean greyflag=false;
// We examine the band names looking for "red...", "green...",
// "blue...".
// Note that the channel numbers we record are indexed from 1, not 0.
for (int i = 0; i < numBands; i++) {
String name = sampleDimensionNames[i].toLowerCase();
System.out.println("name :"+name);
if (name != null) {
if (name.matches("red.*")) {
channelNum[RED] = i + 1;
} else if (name.matches("green.*")) {
channelNum[GREEN] = i + 1;
} else if (name.matches("blue.*")) {
channelNum[BLUE] = i + 1;
}else if(name.matches("gray.*")){
System.out.println("What to do here");
channelNum[RED] = 1;
channelNum[GREEN] = 2;
channelNum[BLUE] = 3;
greyflag=true;
}
}
}
// If we didn't find named bands "red...", "green...", "blue..."
// we fall back to using the first three bands in order
if(greyflag==false){
if (channelNum[RED] < 0 || channelNum[GREEN] < 0
|| channelNum[BLUE] < 0) {
channelNum[RED] = 1;
channelNum[GREEN] = 2;
channelNum[BLUE] = 3;
}
}
// Now we create a RasterSymbolizer using the selected channels
SelectedChannelType[] sct = new SelectedChannelType[cov
.getNumSampleDimensions()];
ContrastEnhancement ce = sf.contrastEnhancement(this.ff.literal(1.0),
ContrastMethod.NORMALIZE);
for (int i = 0; i < numBands; i++) {
sct[i] = sf.createSelectedChannelType(
String.valueOf(channelNum[i]), ce);
System.out.println(String.valueOf(channelNum[i]));
}
RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
ChannelSelection sel =sf.channelSelection(sct[RED]);
if(numBands>1){
sel = sf.channelSelection(sct[RED], sct[GREEN],
sct[BLUE]);
}
sym.setChannelSelection(sel);
return SLD.wrapSymbolizers(sym);
}
I just pass two files as below code
public MapImagePanel() {
this.setLayout(new BorderLayout(0, 0));
this.setBackground(Color.BLUE);
this.setPreferredSize(new Dimension(720, 360));
this.setBlueMarble(new File("E:/tifffilename.TIFF"));
this.setBorderShape(new File("E:/shapefilename.shp"));
try {
this.displayLayers();
} catch (Exception e) {
e.printStackTrace();
}
}
This is how i use this class in main class
//see output in main method
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MapImagePanel panel = new MapImagePanel();
panel.setPreferredSize(new Dimension(1024,768));
panel.setVisible(true);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
frame.show();
TLDR; add the following line to your program start up:
System.setProperty("org.geotools.referencing.forceXY", "true");
From GeoTools FAQ as computer programmers they knew that coordinates would be expressed as longitude,latitude pairs so they could use existing graphics code easily by treating them as a simple (x,y) pair. but for sequence like (x,y) or (y,x) they confused that is why this error is coming.
So, I am showing a route from point A to point B on a Google Map on my Android App. This is all well. What I am doing now is zooming-to-fit both of the markers on the map by doing this:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng marker : markerPoints) {
builder.include(marker);
}
LatLngBounds bounds = builder.build();
int padding = 20; // offset from edges of the map in pixels
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds,
padding);
map.moveCamera(cu);
map.animateCamera(cu);
The problem is that this doesn't include poly lines, so if the route goes outside of the screen, it cuts off the poly line, like this:
Any ideas on how I can zoom-to-fit the poly lines? Thanks!
I tried this code and its works good for me and also i attached output screen here.
LatLng from_Latlng=new LatLng(11.9464816,79.8091988);
LatLng to_Latlong=new LatLng(12.9876327,80.1260089);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(from_Latlng);
builder.include(to_Latlong);
LatLngBounds bounds = builder.build();
GoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100), 2000, null);
Output screen :-
I got it. I just kept track of every LatLng within my Poly Line and added them to the LatLng builder
private class ParserTask extends
AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
// Parsing the data in non-ui thread
#Override
protected List<List<HashMap<String, String>>> doInBackground(
String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
String distance = "";
String duration = "";
if (result.size() < 1) {
Toast.makeText(getBaseContext(), "No Points",
Toast.LENGTH_SHORT).show();
return;
}
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
if (j == 0) { // Get distance from the list
distance = (String) point.get("distance");
continue;
} else if (j == 1) { // Get duration from the list
duration = (String) point.get("duration");
continue;
}
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(8);
lineOptions.color(Color.BLUE);
}
tvDistanceDuration.setText("Distance:" + distance + ", Duration:"
+ duration);
// Drawing polyline in the Google Map for the i-th route
map.addPolyline(lineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
/*
* for (Marker marker : markers) {
* builder.include(marker.getPosition()); }
*/
for (LatLng point : points) {
builder.include(point);
}
LatLngBounds bounds = builder.build();
int padding = 20; // offset from edges of the map in pixels
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds,
padding);
map.moveCamera(cu);
map.animateCamera(cu, 2000, null);
}
}
I would say that while you're building the polyline you keep track of the extents of the line. Then when you zoom use those extents not the points.
I copied from Premkumar's for mine. If you've got more than 2 points and you want to make sure everything fits (maybe you've got two points in the middle, and lots of stuff circling around). This solution works by creating a minLatLng and a maxLatLng and then using the newLatLngBounds solution from Premkumar's answer:
var minLat: Double? = null
var minLng: Double? = null
var maxLat: Double? = null
var maxLng: Double? = null
allLocs!!.forEach {
if (minLat == null) {
minLat = it.latitude
maxLat = it.latitude
minLng = it.longitude
maxLng = it.longitude
} else {
minLat = min(it.latitude, minLat!!)
maxLat = max(it.latitude, maxLat!!)
minLng = min(it.longitude, minLng!!)
maxLng = max(it.longitude, maxLng!!)
}
}
val builder = LatLngBounds.builder()
builder.include(LatLng(minLat!!, minLng!!))
builder.include(LatLng(maxLat!!, maxLng!!))
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 100))
Obviously, if you need this in real time, it would be far more efficient to keep a tally of your mins and maxes every time you get a new location.
Here is my asynctask part where I am putting pin in some location parsed from an XML. This is doing fine for a small location data set but takes a long time when the location data set is large.
private class MapLoader extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
ArrayList<POI>[] mappoiList;
#Override
protected void onPreExecute() {
mapOverlays = mapview.getOverlays();
dialog = new ProgressDialog(MainActivity.this);
dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(MainActivity.baseUrl
+ "latitude=40.9192799&longitude=-74.0657508&distance=20");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
ParserHandler parserHandler = new ParserHandler();
xr.setContentHandler(parserHandler);
xr.parse(new InputSource(url.openStream()));
Log.d("Thread", url.toString());
basicItems = parserHandler.getBasicItems();
featuredItems = parserHandler.getFeaturedItems();
restaurants = parserHandler.getRestaurants();
mapvisibleList = new ArrayList<POI>();
mappoiList = new ArrayList[2];
mappoiList[0] = new ArrayList<POI>();
mappoiList[1] = new ArrayList<POI>();
for (int i = 0; i < featuredItems.size(); i++) {
POI poi = new POI(featuredItems.get(i), 1);
mappoiList[0].add(poi);
}
for (int i = 0; i < restaurants.size(); i++) {
POI poi = new POI(restaurants.get(i), 2);
mappoiList[0].add(poi);
}
for (int i = 0; i < basicItems.size(); i++) {
POI poi = new POI(basicItems.get(i), 0);
mappoiList[1].add(poi);
}
for (int i = 0; i < mappoiList[0].size(); i++) {
if (mappoiList[0] != null) {
mapvisibleList.add(mappoiList[0].get(i));
}
}
for (int i = 0; i < mappoiList[1].size(); i++) {
if (mappoiList[1] != null) {
mapvisibleList.add(mappoiList[1].get(i));
}
}
for (FeaturedItem item : featuredItems) {
Log.d("FEATURED",
item.getName() + "Distance: " + item.getDistance());
}
for (Restaurant item : restaurants) {
Log.d("RESTAURANTS",
item.getName() + "Distance: " + item.getDistance());
}
for (BasicItem item : basicItems) {
Log.d("BASIC",
item.getName() + "Distance: " + item.getDistance());
}
} catch (MalformedURLException e) {
e.printStackTrace();
showErrorDialog("Error", "Malformed URL Error Occurred");
} catch (ParserConfigurationException e) {
e.printStackTrace();
showErrorDialog("Error",
"Parser Configuration Problem Occurred");
} catch (SAXException e) {
e.printStackTrace();
showErrorDialog("Error", "SAX Parser Error Occurred");
} catch (IOException e) {
e.printStackTrace();
showErrorDialog("Error", "IOException Occurred");
} catch (Exception e) {
e.printStackTrace();
}
GlobalData.gBasicItems = basicItems;
GlobalData.gFeaturedItems = featuredItems;
GlobalData.gRestaurants = restaurants;
if (currentLocation != null) {
int curLat = (int) (currentLocation.getLatitude() * 1e6);
int curLon = (int) (currentLocation.getLongitude() * 1e6);
GeoPoint gp = new GeoPoint(curLat, curLon);
mapControl.animateTo(gp);
mapControl.setZoom(14);
OverlayItem item = new OverlayItem(gp, "My Location",
"My Location");
itemizedOverlay1 = new MyItemizedOverlay(drawableFeature,
MainActivity.this, mappoiList[0]);
itemizedOverlay2 = new MyItemizedOverlay(drawableBasic,
MainActivity.this, mappoiList[1]);
itemizedOverlay3 = new MyItemizedOverlay(drawableCurrent,
MainActivity.this, mappoiList[0]);
Log.i("asyncbasic", "" + basicItems.size());
Log.i("asyncfeatured", "" + featuredItems.size());
Log.i("asyncres", "" + restaurants.size());
if (featuredItems != null) {
int featuredLength = featuredItems.size();
for (int i = 0; i < featuredLength; i++) {
FeaturedItem fItem = featuredItems.get(i);
int lat = (int) (Double
.parseDouble(fItem.getLatitude()) * 1e6);
int lon = (int) (Double.parseDouble(fItem
.getLongitude()) * 1e6);
OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
lon), fItem.getName(), "Feature");
itemizedOverlay1.addOverlay(oItem);
Log.i("Map over lay", "Finished one featured");
}
}
if (basicItems != null) {
int basicLength = basicItems.size();
for (int i = 0; i < basicLength; i++) {
BasicItem bItem = basicItems.get(i);
int lat = (int) (Double
.parseDouble(bItem.getLatitude()) * 1e6);
int lon = (int) (Double.parseDouble(bItem
.getLongitude()) * 1e6);
OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
lon), bItem.getName(), "Basic");
itemizedOverlay2.addOverlay(oItem);
Log.i("Map over lay", "Finished one Basic");
}
}
if (restaurants != null) {
int resLength = restaurants.size();
for (int i = 0; i < resLength; i++) {
Restaurant res = restaurants.get(i);
int lat = (int) (Double.parseDouble(res.getLatitude()) * 1e6);
int lon = (int) (Double.parseDouble(res.getLongitude()) * 1e6);
OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
lon), res.getName(), "Restaurant");
itemizedOverlay1.addOverlay(oItem);
Log.i("Map over lay", "Finished one Restaurant");
}
}
itemizedOverlay3.addOverlay(item);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mapOverlays.clear();
mapOverlays.add(itemizedOverlay1);
mapOverlays.add(itemizedOverlay2);
mapOverlays.add(itemizedOverlay3);
mapview.postInvalidate();
dialog.dismiss();
}
}
I learned about using getLatitudeSpan and getLongitudeSpan to get rid of this problem, but I am not too clear on where and how to use it in my async task. Any suggestions?
Please give exact data size where the time taken is long, Also try profiling the code to see time taken for each code block.
But looking at the code, the looping through all those variables would have a significant effect on time if the data being operated on increased,
try simplifying/combining the loops,
e.g this loop
for (int i = 0; i < featuredItems.size(); i++) {
POI poi = new POI(featuredItems.get(i), 1);
mappoiList[0].add(poi);
}
and this one
if (featuredItems != null) {
int featuredLength = featuredItems.size();
for (int i = 0; i < featuredLength; i++) {
FeaturedItem fItem = featuredItems.get(i);
int lat = (int) (Double
.parseDouble(fItem.getLatitude()) * 1e6);
int lon = (int) (Double.parseDouble(fItem
.getLongitude()) * 1e6);
OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
lon), fItem.getName(), "Feature");
itemizedOverlay1.addOverlay(oItem);
Log.i("Map over lay", "Finished one featured");
}
}
can't be combined?
also this loop
for (int i = 0; i < basicItems.size(); i++) {
POI poi = new POI(basicItems.get(i), 0);
mappoiList[1].add(poi);
}
and this
if (basicItems != null) {
int basicLength = basicItems.size();
for (int i = 0; i < basicLength; i++) {
BasicItem bItem = basicItems.get(i);
int lat = (int) (Double
.parseDouble(bItem.getLatitude()) * 1e6);
int lon = (int) (Double.parseDouble(bItem
.getLongitude()) * 1e6);
OverlayItem oItem = new OverlayItem(new GeoPoint(lat,
lon), bItem.getName(), "Basic");
itemizedOverlay2.addOverlay(oItem);
Log.i("Map over lay", "Finished one Basic");
}
}
can also be combined,
I think problem is not about overlay. You are getting all items using sax parser this is taking your musch time. Your trying to get all elements and then adding it to map. If you modify your code to as you get an single element update to overlay and populate it may this will fast your execution.
If your still suffering from same issue try to add elements using separate thread or canvas object of the overlay (by projection of geo point).
You might want to take a look at implementing a Producer-Consumer model where the consumer will be the map itself and the producer will be the logic that generates information for a pin.
You are using a sax parser that's quite time consuming,use a object model representative like a json,that may be easily parsed and so can be plotted on a map.
//Few suggestions that may itself reduce the time problem you are facing.
Only plot the pins and on click open a pop up to display further details inside it.