我正在开发一个实现路线搜索功能的应用程序,用户输入起点和终点,然后通过switch小部件可以绘制结果的路线。
界面和地图是流动的,绘制1条折线时会发生问题。
我正在使用asynctask加载路线的坐标数据并绘制它们。
要获取坐标,我使用Android Maps Utils解码并简化了折线。每条折线包含大约300个点,总共有40条折线。
我还使用服务来处理搜索结果,效果很好。
我还能做些什么来优化折线负载?我已经研究过,但结果与我已经在做的类似。
期待您的帮助!
代码:
MapDemoActivity.class
public class MapDemoActivity extends AppCompatActivity
implements
GoogleMap.OnMyLocationButtonClickListener,
GoogleMap.OnMyLocationClickListener {
private SupportMapFragment mapFragment;
public static GoogleMap map;
Location mCurrentLocation;
private final static String KEY_LOCATION = "location";
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
protected static final String TAG = "LocationOnOff";
private GoogleApiClient googleApiClient;
final static int REQUEST_LOCATION = 199;
public static final String EXTRA_CIRCULAR_REVEAL_X = "EXTRA_CIRCULAR_REVEAL_X";
public static final String EXTRA_CIRCULAR_REVEAL_Y = "EXTRA_CIRCULAR_REVEAL_Y";
View rootLayout;
private int revealX;
private int revealY;
FloatingActionButton searchButton, checkButton, checkButtonDestino, reset;
ImageView markerOrigen;
private RoundedView mRoundedIndicatorOrigin;
private RoundedView mRoundedIndicatorDestination;
TextView source_location, destination_location;
String type = "";
Intent intentAnim = null;
private GoogleMap.OnCameraIdleListener onCameraIdleListener;
Marker source_location_marker, destination_location_marker;
double LatOrigen;
double LonOrigen;
double LatDestino;
double LonDestino;
private SlidingUpPanelLayout mLayout;
SlidingUpPanelLayout dragView;
ArrayList<Integer> validadorFinal = new ArrayList<Integer>();
ArrayList<Switch> listSwitch = new ArrayList<Switch>();
private static final PatternItem DOT = new Dot();
private static final int PATTERN_DASH_LENGTH_PX = 50;
private static final PatternItem DASH = new Dash(PATTERN_DASH_LENGTH_PX);
private static final int PATTERN_GAP_LENGTH_PX = 10;
private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);
private static final List<PatternItem> PATTERN_POLYLINE_DOTTED = Arrays.asList(DASH, DOT, GAP);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_demo_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.arrow_left);
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mMessageFilterResult, new IntentFilter("validador"));
intentAnim = getIntent();
rootLayout = findViewById(R.id.root_layout);
if (savedInstanceState == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
intentAnim.hasExtra(EXTRA_CIRCULAR_REVEAL_X) &&
intentAnim.hasExtra(EXTRA_CIRCULAR_REVEAL_Y)) {
startAnim();
}
if (TextUtils.isEmpty(getResources().getString(R.string.google_maps_api_key))) {
throw new IllegalStateException("You forgot to supply a Google Maps API key");
}
mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
if (mapFragment != null) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap map) {
loadMap(map);
}
});
} else {
Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show();
}
initView();
}
protected void startAnim(){
rootLayout.setVisibility(View.INVISIBLE);
revealX = intentAnim.getIntExtra(EXTRA_CIRCULAR_REVEAL_X, 0);
revealY = intentAnim.getIntExtra(EXTRA_CIRCULAR_REVEAL_Y, 0);
ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
revealActivity(revealX, revealY);
rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
} else {
rootLayout.setVisibility(View.VISIBLE);
}
}
public void initView(){
searchButton = (FloatingActionButton)findViewById(R.id.fab);
//dataResultView.setVisibility(View.VISIBLE);
markerOrigen = (ImageView)findViewById(R.id.markerTarget);
dragView = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
checkButton = (FloatingActionButton)findViewById(R.id.fab2);
checkButtonDestino = (FloatingActionButton)findViewById(R.id.fab3);
reset = (FloatingActionButton) findViewById(R.id.reset);
resetMap();
mRoundedIndicatorOrigin = (RoundedView)findViewById(R.id.rounded_indicator_source);
mRoundedIndicatorDestination = (RoundedView)findViewById(R.id.rounded_indicator_destination);
source_location=(TextView) findViewById(R.id.source_location);
source_location.setTag(0);
destination_location=(TextView)findViewById(R.id.destination_location);
destination_location.setTag(0);
searchButton.setTag("1");
searchOptions();
mLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
mLayout.setAnchorPoint(0.7f);
//mLayout.setPanelState(SlidingUpPanelLayout.PanelState.ANCHORED);
mLayout.addPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
Log.i(TAG, "onPanelSlide, offset " + slideOffset);
}
@Override
public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState previousState, SlidingUpPanelLayout.PanelState newState) {
Log.i(TAG, "onPanelStateChanged " + newState);
}
});
mLayout.setFadeOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
mLayout.setAnchorPoint(0.7f);
mLayout.setPanelState(SlidingUpPanelLayout.PanelState.ANCHORED);
}
});
}
private void resetMap(){
reset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
map.clear();
map.setOnCameraIdleListener(null);
source_location.setText(null);
destination_location.setText(null);
mRoundedIndicatorOrigin.setChecked(false);
mRoundedIndicatorDestination.setChecked(false);
searchButton.setTag("1");
type="";
if (listSwitch.isEmpty()) {
//Nothing
}else {
for (int i=0; i <= 79; i++) {
if (listSwitch.get(i).isChecked()) {
listSwitch.get(i).setChecked(false);
}
}
}
searchButton.hide();
checkButtonDestino.hide();
checkButton.hide();
reset.hide();
dragView.setPanelHeight(0);
}
});
}
private void searchOptions() {
source_location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
configureCameraIdle();
mRoundedIndicatorOrigin.setChecked(true);
mRoundedIndicatorDestination.setChecked(false);
map.setOnCameraIdleListener(onCameraIdleListener);
checkButton.show();
markerOrigen.setVisibility(View.VISIBLE);
}
});
destination_location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
configureCameraIdle2();
mRoundedIndicatorOrigin.setChecked(false);
mRoundedIndicatorDestination.setChecked(true);
map.setOnCameraIdleListener(onCameraIdleListener);
checkButtonDestino.show();
markerOrigen.setVisibility(View.VISIBLE);
}
});
}
private void configureCameraIdle() {
getDataCameraIdle();
onCameraIdleListener = new GoogleMap.OnCameraIdleListener() {
@Override
public void onCameraIdle() {
getDataCameraIdle();
}
};
}
private void getDataCameraIdle(){
LatLng latLng = map.getCameraPosition().target;
Location mLocation = new Location("");
mLocation.setLatitude(latLng.latitude);
mLocation.setLongitude(latLng.longitude);
new AsyncGeocoder().execute(new AsyncGeocoderObject(
new Geocoder(this),
mLocation,
source_location
));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Origen");
checkButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkButton.setTag("1");
map.setOnCameraIdleListener(null);
//Log.d("TAG", "click checkbutton");
if (source_location_marker!=null)
{
source_location_marker.remove();
}
LatOrigen = latLng.latitude;
LonOrigen = latLng.longitude;
source_location_marker=map.addMarker(markerOptions);
markerOrigen.setVisibility(View.GONE);
checkButton.hide();
source_location.setTag(1);
checkSearchButtonStatus();
}
});
}
private void configureCameraIdle2() {
getDataCameraIdle2();
onCameraIdleListener = new GoogleMap.OnCameraIdleListener() {
@Override
public void onCameraIdle() {
getDataCameraIdle2();
}
};
}
private void getDataCameraIdle2(){
LatLng latLng = map.getCameraPosition().target;
Location mLocation = new Location("");
mLocation.setLatitude(latLng.latitude);
mLocation.setLongitude(latLng.longitude);
new AsyncGeocoder().execute(new AsyncGeocoderObject(
new Geocoder(this),
mLocation,
destination_location
));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Destino");
checkButtonDestino.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkButtonDestino.setTag("1");
map.setOnCameraIdleListener(null);
Log.d("TAG", "click checkbutton destino");
if (destination_location_marker!=null)
{
destination_location_marker.remove();
}
LatDestino = latLng.latitude;
LonDestino= latLng.longitude;
destination_location_marker=map.addMarker(markerOptions);
markerOrigen.setVisibility(View.GONE);
checkButtonDestino.hide();
destination_location.setTag("1");
checkSearchButtonStatus();
}
});
}
private void checkSearchButtonStatus() {
if(source_location.getTag()!=null && destination_location.getTag()!=null){
type = source_location.getTag().toString() + destination_location.getTag().toString();
}
switch (type) {
case "10":
//Show toast polyline 1 ("A")
Toast.makeText(getApplicationContext(), "Selecciona un destino", Toast.LENGTH_LONG).show();
break;
case "01":
Toast.makeText(this, "Selecciona un origen", Toast.LENGTH_SHORT).show();
break;
case "11":
initSearchService();
searchButton.show();
break;
}
}
public void initSearchService(){
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(searchButton.getTag().toString()=="1"){
Intent intent = new Intent(MapDemoActivity.this, searchService.class);
intent.putExtra("LatOrigen",LatOrigen);
intent.putExtra("LonOrigen",LonOrigen);
intent.putExtra("LatDestino",LatDestino);
intent.putExtra("LonDestino",LonDestino);
startService(intent);
int sizeInPixel = getApplicationContext().getResources().getDimensionPixelSize(R.dimen.dragView);
dragView.setPanelHeight(sizeInPixel);
source_location.setTag("0");
destination_location.setTag("0");
searchButton.setTag("0");
searchButton.hide();
reset.show();
}else {
}
}
});
}
protected void revealActivity(int x, int y) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
float finalRadius = (float) (Math.max(rootLayout.getWidth(), rootLayout.getHeight()) * 1.1);
// create the animator for this view (the start radius is zero)
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootLayout, x, y, 0, finalRadius);
circularReveal.setDuration(1190);
circularReveal.setInterpolator(new AccelerateInterpolator());
// make the view visible and start the animation
rootLayout.setVisibility(View.VISIBLE);
circularReveal.start();
} else {
finish();
}
}
@SuppressLint("MissingPermission")
protected void loadMap(GoogleMap googleMap) {
map = googleMap;
if (map != null) {
// Map is ready
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(this);
map.setOnMyLocationClickListener(this);
changeGPSIcon();
try {
// Customise the styling of the base map using a JSON object defined
// in a raw resource file.
boolean success = map.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this, R.raw.style_json));
if (!success) {
}
} catch (Resources.NotFoundException e) {
}
LatLng marker = new LatLng(19.407021, -102.046595);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(marker, 13));
//Zoom Preferences
map.setMinZoomPreference(12);
map.setMaxZoomPreference(19);
} else {
Toast.makeText(this, "Error - Map was null!!", Toast.LENGTH_SHORT).show();
}
}
public void changeGPSIcon() {
ImageView locationButton = (ImageView) mapFragment.getView().findViewById(Integer.parseInt("2"));
locationButton.setVisibility(View.GONE);
FloatingActionButton gpsButton = findViewById(R.id.gpsbutton);
gpsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
locationButton.callOnClick();
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
MapDemoActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
switch (requestCode) {
case 0x1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission is granted", Toast.LENGTH_SHORT).show();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
enableMyLocation();
}
}
}
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission to access the location is missing.
PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
Manifest.permission.ACCESS_FINE_LOCATION, true);
} else if (map != null) {
// Access to the location has been granted to the app.
map.setMyLocationEnabled(true);
}
}
@Override
public boolean onMyLocationButtonClick() {
enableLoc();
return false;
}
@Override
public void onMyLocationClick(@NonNull Location location) {
Toast.makeText(this, "Ubicación actual", Toast.LENGTH_LONG).show();
}
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
super.onSaveInstanceState(savedInstanceState);
}
private void enableLoc() {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(MapDemoActivity.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d("Location error", "Location error " + connectionResult.getErrorCode());
}
}).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(MapDemoActivity.this, REQUEST_LOCATION);
//finish();
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
}
}
});
}
}
@Override
public void onBackPressed() {
if (mLayout != null &&
(mLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED || mLayout.getPanelState() == SlidingUpPanelLayout.PanelState.ANCHORED)) {
mLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
} else {
super.onBackPressed();
}
}
private BroadcastReceiver mMessageFilterResult = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getBundleExtra("extra");
if (bundle != null) {
validadorFinal = (ArrayList<Integer>) bundle.getIntegerArrayList("validadorFinal_");
} else {
}
new polylinePrinter().execute();
}
};
protected class polylinePrinter extends AsyncTask {
PolylineOptions pUnidad1PalitoVerdeIda;
PolylineOptions pUnidad1PalitoVerdeVuelta;
PolylineOptions pUnidad1ManantialesIda;
PolylineOptions pUnidad1ManantialesVuelta;
PolylineOptions pUnidad1SanJoseIda;
PolylineOptions pUnidad1SanJoseVuelta;
PolylineOptions pConstiZumpi2AIda;
PolylineOptions pConstiZumpi2AVuelta;
PolylineOptions pConstiJica2Ida;
PolylineOptions pConstiJica2Vuelta;
List<LatLng> simplifydecodedRuta1Ida;
List<LatLng> simplifydecodedRuta1Vuelta;
List<LatLng> simplifydecodedRuta1MIda;
List<LatLng> simplifydecodedRuta1MVuelta;
List<LatLng> simplifydecodedRuta1SIda;
List<LatLng> simplifydecodedRuta1SVuelta;
List<LatLng> simplifydecodedRuta3Ida;
List<LatLng> simplifydecodedRuta3Vuelta;
List<LatLng> simplifydecodedRuta5Ida;
List<LatLng> simplifydecodedRuta5Vuelta;
@Override
protected Object doInBackground(Object[] objects) {
double tolerance = 20;
if (validadorFinal.get(0)==1){
simplifydecodedRuta1Ida = PolyUtil.simplify(ConstantsRoutes.decodedRuta1Ida, tolerance);
simplifydecodedRuta1Vuelta = PolyUtil.simplify(ConstantsRoutes.decodedRuta1Vuelta, tolerance);
Loader1Ida();
Loader1Vuelta();
}
if (validadorFinal.get(1)==1){
simplifydecodedRuta1MIda = PolyUtil.simplify(ConstantsRoutes.decodedRuta1MIda, tolerance);
simplifydecodedRuta1MVuelta = PolyUtil.simplify(ConstantsRoutes.decodedRuta1MVuelta, tolerance);
Loader1MIda();
Loader1MVuelta();
}
if (validadorFinal.get(2)==1){
simplifydecodedRuta1SIda = PolyUtil.simplify(ConstantsRoutes.decodedRuta1SIda, tolerance);
simplifydecodedRuta1SVuelta = PolyUtil.simplify(ConstantsRoutes.decodedRuta1SVuelta, tolerance);
Loader1SIda();
Loader1SVuelta();
}
if (validadorFinal.get(3)==1){
simplifydecodedRuta2Ida = PolyUtil.simplify(ConstantsRoutes.decodedRuta2Ida, tolerance);
simplifydecodedRuta2Vuelta = PolyUtil.simplify(ConstantsRoutes.decodedRuta2Vuelta, tolerance);
Loader2Ida();
Loader2Vuelta();
}
if (validadorFinal.get(4)==1){
Loader2AIda();
Loader2AVuelta();
}
if (validadorFinal.get(5)==1){
simplifydecodedRuta3Ida = PolyUtil.simplify(ConstantsRoutes.decodedRuta3Ida, tolerance);
simplifydecodedRuta3Vuelta = PolyUtil.simplify(ConstantsRoutes.decodedRuta3Vuelta, tolerance);
Loader3Ida();
Loader3Vuelta();
}
return null;
}
protected void onPostExecute(Object result) {
loadSwitches();
if(validadorFinal.get(0)==1){
shower1Vuelta();
Shower1Ida();
}
if (validadorFinal.get(1)==1){
shower1MIda();
shower1MVuelta();
}
if (validadorFinal.get(2)==1){
shower1SIda();
shower1SVuelta();
}
if (validadorFinal.get(3)==1){
shower2Ida();
shower2Vuelta();
}
if (validadorFinal.get(4)==1){
shower2AIda();
shower2AVuelta();
}
if (validadorFinal.get(5)==1){
shower3Ida();
shower3Vuelta();
}
}
private void loadSwitches(){
Switch switch_ida1 = (Switch) findViewById(R.id.switchIdaRuta1);
Switch switch_vuelta1 = (Switch) findViewById(R.id.switchVueltaRuta1);
Switch switch_ida1M = (Switch) findViewById(R.id.switchIdaRuta1M);
Switch switch_vuelta1M = (Switch) findViewById(R.id.switchVueltaRuta1M);
Switch switch_ida1S = (Switch) findViewById(R.id.switchIdaRuta1S);
Switch switch_vuelta1S = (Switch) findViewById(R.id.switchVueltaRuta1S);
Switch switch_ida2A = (Switch) findViewById(R.id.switchIdaRuta2A);
Switch switch_vuelta2A = (Switch) findViewById(R.id.switchVueltaRuta2A);
Switch switch_ida2 = (Switch) findViewById(R.id.switchIdaRuta2);
Switch switch_vuelta2 = (Switch) findViewById(R.id.switchVueltaRuta2);
Switch switch_ida3 = (Switch) findViewById(R.id.switchIdaRuta3);
Switch switch_vuelta3 = (Switch) findViewById(R.id.switchVueltaRuta3);
Switch switch_ida4 = (Switch) findViewById(R.id.switchIdaRuta4);
Switch switch_vuelta4 = (Switch) findViewById(R.id.switchVueltaRuta4);
Switch switch_ida5 = (Switch) findViewById(R.id.switchIdaRuta5);
Switch switch_vuelta5 = (Switch) findViewById(R.id.switchVueltaRuta5);
listSwitch.add(0,switch_ida1);
listSwitch.add(1, switch_vuelta1);
listSwitch.add(2,switch_ida1M);
listSwitch.add(3,switch_vuelta1M);
listSwitch.add(4,switch_ida1S);
listSwitch.add(5,switch_vuelta1S);
}
private void Loader1Ida(){
pUnidad1PalitoVerdeIda = new PolylineOptions();
pUnidad1PalitoVerdeIda.addAll(simplifydecodedRuta1Ida)
.color(Color.parseColor("#2196F3")); //Color blue
}
private void Shower1Ida(){
LinearLayout linearLayout1 = (LinearLayout) findViewById(R.id.layoutRuta1);
linearLayout1.setVisibility(View.VISIBLE);
final Polyline[] Unidad1PalitoVerdeIda = new Polyline[1];
listSwitch.get(0).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Unidad1PalitoVerdeIda[0] = map.addPolyline(pUnidad1PalitoVerdeIda);
Unidad1PalitoVerdeIda[0].setClickable(true);
Unidad1PalitoVerdeIda[0].setTag("Unidad1PalitoVerdeIda");
Unidad1PalitoVerdeIda[0].setWidth(8);
Unidad1PalitoVerdeIda[0].setPattern(PATTERN_POLYLINE_DOTTED);
} else {
Unidad1PalitoVerdeIda[0].remove();
}
}
});
//39 Routes more
}
答案 0 :(得分:0)
如果您绘制的不是全部,而是仅针对折线的每个缩放级别“特殊”(路径改变的点)点进行概括,则可以减少绘制折线时的屏幕地图滞后。要确定路径的“特殊”点,可以使用例如Ramer-Douglas-Peucker algorithm:
尤其可以使用Google Maps Android API Utility Library
PolyUtil.simplify()
方法作为其实现。
此外,here可以找到它的Java实现(带有注释):
private static class Point extends Pair<Double, Double> {
Point(Double key, Double value) {
super(key, value);
}
@Override
public String toString() {
return String.format("(%f, %f)", getKey(), getValue());
}
}
private static double perpendicularDistance(Point pt, Point lineStart, Point lineEnd) {
double dx = lineEnd.getKey() - lineStart.getKey();
double dy = lineEnd.getValue() - lineStart.getValue();
// Normalize
double mag = Math.hypot(dx, dy);
if (mag > 0.0) {
dx /= mag;
dy /= mag;
}
double pvx = pt.getKey() - lineStart.getKey();
double pvy = pt.getValue() - lineStart.getValue();
// Get dot product (project pv onto normalized direction)
double pvdot = dx * pvx + dy * pvy;
// Scale line direction vector and subtract it from pv
double ax = pvx - pvdot * dx;
double ay = pvy - pvdot * dy;
return Math.hypot(ax, ay);
}
private static void ramerDouglasPeucker(List<Point> pointList, double epsilon, List<Point> out) {
if (pointList.size() < 2) throw new IllegalArgumentException("Not enough points to simplify");
// Find the point with the maximum distance from line between the start and end
double dmax = 0.0;
int index = 0;
int end = pointList.size() - 1;
for (int i = 1; i < end; ++i) {
double d = perpendicularDistance(pointList.get(i), pointList.get(0), pointList.get(end));
if (d > dmax) {
index = i;
dmax = d;
}
}
// If max distance is greater than epsilon, recursively simplify
if (dmax > epsilon) {
List<Point> recResults1 = new ArrayList<>();
List<Point> recResults2 = new ArrayList<>();
List<Point> firstLine = pointList.subList(0, index + 1);
List<Point> lastLine = pointList.subList(index, pointList.size());
ramerDouglasPeucker(firstLine, epsilon, recResults1);
ramerDouglasPeucker(lastLine, epsilon, recResults2);
// build the result list
out.addAll(recResults1.subList(0, recResults1.size() - 1));
out.addAll(recResults2);
if (out.size() < 2) throw new RuntimeException("Problem assembling output");
} else {
// Just return start and end points
out.clear();
out.add(pointList.get(0));
out.add(pointList.get(pointList.size() - 1));
}
}
更改double epsilon
的值,您可以为每个缩放级别创建减少的“一般”路径点列表,并减少地图滞后。