Strange behavior of GeoPoint and / or android.maps.Projection when panning MapView at maximum zoom level

I had a strange problem when points get offset using the google map package.

I have a MapView with the route displayed on it. I noticed that if I zoom in and then move around, my route is cut off near the edges of the window. After much debugging of my own code, I found that even a simple case like this was enough to reproduce the problem:

GeoPoint midPoint = projection.fromPixels(mapView.getWidth()/2, mapView.getHeight()/2); GeoPoint nextPoint = new GeoPoint(midPoint.getLatitudeE6(), midPoint.getLongitudeE6()); pathPaint.setColor(0xFF00FF00); projection.toPixels(midPoint, screenPoint); canvas.drawCircle(screenPoint.x, screenPoint.y, 5, pathPaint); pathPaint.setColor(0xFF0000FF); projection.toPixels(nextPoint, screenPoint); canvas.drawCircle(screenPoint.x, screenPoint.y, 5, pathPaint); 

The Projection class returned by MapView.getProjection () is used to translate coordinate coordinates in GeoPoint. He then creates a second GeoPoint using the same lat / long. Finally, he translates both of these GeoPoints back to the screen coordinates and draws two circles, one on top of the other, in this place.

In addition, when you roll, the second circle becomes offset from the first. They have identical lat / lon coordinates (I check after drawing), but I end up getting translations to different screen coordinates. My debugging focused on horizontal panning, but I believe that vertical panning might run into a similar problem based on what I saw with my application source code.

As far as I can tell, all the points created by the map package work fine, but all the points created by calling the new GeoPoint (lat, lon) demonstrate this behavior.

I created a simple truncated program that demonstrates this behavior, which is inserted below. (Card tiles will not load because I did not sign them, but you do not need them to see the problem.) Just start it, zoom in and start panning left or right. Watch the green and blue dots diverge, and watch the Log.d seals, which state that they still have equal lat / lon.

(Is there a better / preferred way to publish sample projects? Sorry, this is my first post here.)

SRC / example / MYSAMPLE / MapOverlay.java:

 package example.mysample; import java.util.ArrayList; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.RadialGradient; import android.graphics.Shader; import android.view.MotionEvent; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.Projection; import android.util.Log; class MapOverlay extends Overlay { public MapOverlay(MapScreen activity) { super(); paint = new Paint(); paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setAntiAlias(true); } @Override public boolean onTouchEvent(MotionEvent e, MapView mapView) { int motionAction = e.getAction(); if ( motionAction == MotionEvent.ACTION_MOVE ) { dragging = true; } if ( motionAction == MotionEvent.ACTION_UP || motionAction == MotionEvent.ACTION_CANCEL ) { dragging = false; } return super.onTouchEvent(e, mapView); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { if (!shadow && !dragging) { Projection projection = mapView.getProjection(); // Draw two circles at the center // One with a virgin point, one that we constructed with the same coordinates GeoPoint midPoint = projection.fromPixels(mapView.getWidth()/2, mapView.getHeight()/2); GeoPoint nextPoint = new GeoPoint(midPoint.getLatitudeE6(), midPoint.getLongitudeE6()); paint.setColor(0xFF00FF00); projection.toPixels(midPoint, screenPoint); canvas.drawCircle(screenPoint.x, screenPoint.y, 5, paint); paint.setColor(0xFF0000FF); projection.toPixels(nextPoint, screenPoint); canvas.drawCircle(screenPoint.x, screenPoint.y, 5, paint); // These print EQUAL. Log.d("BKC DEBUG", "Midpoint and our own midpoint have " + ((midPoint.getLatitudeE6() == nextPoint.getLatitudeE6()) ? "EQUAL" : "UNEQUAL") + " latitudes, and " + ((midPoint.getLongitudeE6() == nextPoint.getLongitudeE6()) ? "EQUAL" : "UNEQUAL") + " longitudes"); } } private Paint paint; private boolean dragging; private Point screenPoint = new Point(); } 

SRC / example / MYSAMPLE / MapScreen.java:

 package example.mysample; import android.os.Bundle; import android.view.View; import android.widget.Toast; import android.util.Log; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.GeoPoint; public class MapScreen extends MapActivity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.map); mapView = (MapView)findViewById(R.id.map_map); mapView.setBuiltInZoomControls(true); mapView.getOverlays().add(new MapOverlay(this)); MapController controller; controller = mapView.getController(); controller.setZoom(17); controller.animateTo(new GeoPoint(36000000, -90000000)); } @Override public boolean isRouteDisplayed() { return true; } private MapView mapView; } 

Res / layout / map.xml:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#414141" > <com.google.android.maps.MapView android:id="@+id/map_map" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginLeft="3dip" android:layout_marginRight="3dip" android:layout_marginTop="3dip" android:layout_marginBottom="3dip" android:apiKey="0jPQdwUtQGBYfPALki6ghGG_X9Jpf-SllYckR4w" android:layout_centerInParent="true" android:clickable="true" /> </RelativeLayout> 

AndroidManifest.xml:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="example.mysample" android:versionCode="1" android:versionName="2.0.1"> <uses-sdk android:minSdkVersion="4" /> <!--uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /--> <!--uses-permission android:name="android.permission.READ_PHONE_STATE" /--> <uses-permission android:name="android.permission.INTERNET" /> <!--uses-permission android:name="android.permission.WAKE_LOCK" /--> <!--uses-permission android:name="android.permission.READ_LOGS" /--> <!--uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /--> <!--application android:name="src.example.mysample.AppMain" android:label="MySample" android:icon="@drawable/icon_android" android:theme="@android:style/Theme.NoTitleBar" --> <application android:name="android.app.Application" android:label="MySample" > <uses-library android:name="com.google.android.maps"/> <!-- Main activity --> <activity android:name="example.mysample.MapScreen" android:clearTaskOnLaunch="true" android:label="MySample" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Other activities --> <!--activity android:name="example.mysample.SomethingElse" android:label="Something" android:screenOrientation="portrait"/--> </application> </manifest> 

build.xml (unchanged from the template):

 <?xml version="1.0" encoding="UTF-8"?> <project name="PROJECT_NAME" default="help"> <!-- The local.properties file is created and updated by the 'android' tool. It contains the path to the SDK. It should *NOT* be checked into Version Control Systems. --> <property file="local.properties" /> <!-- The build.properties file can be created by you and is never touched by the 'android' tool. This is the place to change some of the default property values used by the Ant rules. Here are some properties you may want to change/update: source.dir The name of the source directory. Default is 'src'. out.dir The name of the output directory. Default is 'bin'. Properties related to the SDK location or the project target should be updated using the 'android' tool with the 'update' action. This file is an integral part of the build system for your application and should be checked into Version Control Systems. --> <property file="build.properties" /> <!-- The default.properties file is created and updated by the 'android' tool, as well as ADT. This file is an integral part of the build system for your application and should be checked into Version Control Systems. --> <property file="default.properties" /> <!-- Custom Android task to deal with the project target, and import the proper rules. This requires ant 1.6.0 or above. --> <path id="android.antlibs"> <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" /> <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" /> <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" /> </path> <taskdef name="setup" classname="com.android.ant.SetupTask" classpathref="android.antlibs" /> <!-- extension targets. Uncomment the ones where you want to do custom work in between standard targets --> <!-- <target name="-pre-build"> </target> <target name="-pre-compile"> </target> [This is typically used for code obfuscation. Compiled code location: ${out.classes.absolute.dir} If this is not done in place, override ${out.dex.input.absolute.dir}] <target name="-post-compile"> </target> --> <!-- Execute the Android Setup task that will setup some properties specific to the target, and import the build rules files. The rules file is imported from <SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml To customize existing targets, there are two options: - Customize only one target: - copy/paste the target into this file, *before* the <setup> task. - customize it to your needs. - Customize the whole script. - copy/paste the content of the rules files (minus the top node) into this file, *after* the <setup> task - disable the import of the rules by changing the setup task below to <setup import="false" />. - customize to your needs. --> <setup /> </project> 
+4
source share
1 answer

I also come across this problem - it seems to be a bug in the Android Mapview API - I think the problem for the star is: http://code.google.com/p/android/issues/detail?id=17387&can=5&colspec=ID % 20Type% 20Status% 20Owner% 20Summary% 20Stars is also a possible workaround, which is ugly but works to be included in the comments - you basically identify the error and adjust the result accordingly.

+1
source

Source: https://habr.com/ru/post/1344705/


All Articles