trucos hobba hevvo hartico habtium habbo fantasy creditos comandos android gps rotation android-imageview

android - hevvo - hobba



Girar una vista de imagen como una brújula(con el "polo norte" en otro lugar) (3)

Debería poder establecer la matriz en ImageView sin tener que volver a crear el mapa de bits cada vez, y er ... ''normalizar'' (¿esa es la palabra?) Las lecturas.

float b = mLoc.getBearing(); if(b < 0) b = 360 + b; float h = item.mHeading; if(h < 0) h = 360 + h; float r = (h - b) - 360; matrix.reset(); matrix.postRotate(r, width/2, height/2);

En el ejemplo anterior, mLoc es una ubicación devuelta por un proveedor de gps y getBearing devuelve la cantidad de grados al este del norte de la dirección de viaje actual. item.mHeading se ha calculado utilizando la función Location.bearingTo () usando mLoc y la ubicación del elemento. ancho y alto son las dimensiones de la vista de la imagen.

Por lo tanto, asegúrese de que sus variables estén en grados y no radianes, e intente ''normalizar'' (obteniendo títulos en el rango de 0-360 y no de -180-180). Además, si los resultados están desactivados en 180 grados, asegúrate de llevar el rumbo hacia tu objetivo, en lugar de los grados de tu objetivo hacia ti.

La matriz anterior se puede establecer en un ImageView que tiene un ScaleType.Matrix

imageView.setMatrix(matrix); imageview.setScaleType(ScaleType.Matrix);

Dado que gira alrededor del punto central de imageView (ancho / 2, alto / 2 en la rotación posterior), su dibujo debe estar apuntando hacia arriba y girará en el momento del dibujo, en lugar de volver a crear un nuevo mapa de bits cada vez .

Estoy perplejo con respecto a cómo implementar una "brújula personal", es decir, una brújula que apunta a un rumbo específico en lugar del "polo norte" estándar ... desafortunadamente, mi intento actual ha salido mal (no apunta a la rodamiento dado). También está conectado con el acelerador para poder ajustarse dinámicamente de acuerdo con la forma en que el usuario esté girando.

Aquí está mi intento actual (el método onSensorChanged() que actualiza la flecha):

public void onSensorChanged( SensorEvent event ) { // If we don''t have a Location, we break out if ( LocationObj == null ) return; float azimuth = event.values[0]; float baseAzimuth = azimuth; GeomagneticField geoField = new GeomagneticField( Double .valueOf( LocationObj.getLatitude() ).floatValue(), Double .valueOf( LocationObj.getLongitude() ).floatValue(), Double.valueOf( LocationObj.getAltitude() ).floatValue(), System.currentTimeMillis() ); azimuth += geoField.getDeclination(); // converts magnetic north into true north //Correct the azimuth azimuth = azimuth % 360; //This is where we choose to point it float direction = azimuth + LocationObj.bearingTo( destinationObj ); rotateImageView( arrow, R.drawable.arrow, direction ); //Set the field if( baseAzimuth > 0 && baseAzimuth < 45 ) fieldBearing.setText("S"); else if( baseAzimuth >= 45 && baseAzimuth < 90 ) fieldBearing.setText("SW"); else if( baseAzimuth > 0 && baseAzimuth < 135 ) fieldBearing.setText("W"); else if( baseAzimuth > 0 && baseAzimuth < 180 ) fieldBearing.setText("NW"); else if( baseAzimuth > 0 && baseAzimuth < 225 ) fieldBearing.setText("N"); else if( baseAzimuth > 0 && baseAzimuth < 270 ) fieldBearing.setText("NE"); else if( baseAzimuth > 0 && baseAzimuth < 315 ) fieldBearing.setText("E"); else if( baseAzimuth > 0 && baseAzimuth < 360 ) fieldBearing.setText("SE"); else fieldBearing.setText("?"); }

Y aquí está el método que gira el ImageView ( rotateImageView() ):

private void rotateImageView( ImageView imageView, int drawable, float rotate ) { // Decode the drawable into a bitmap Bitmap bitmapOrg = BitmapFactory.decodeResource( getResources(), drawable ); // Get the width/height of the drawable DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int width = bitmapOrg.getWidth(), height = bitmapOrg.getHeight(); // Initialize a new Matrix Matrix matrix = new Matrix(); // Decide on how much to rotate rotate = rotate % 360; // Actually rotate the image matrix.postRotate( rotate, width, height ); // recreate the new Bitmap via a couple conditions Bitmap rotatedBitmap = Bitmap.createBitmap( bitmapOrg, 0, 0, width, height, matrix, true ); //BitmapDrawable bmd = new BitmapDrawable( rotatedBitmap ); //imageView.setImageBitmap( rotatedBitmap ); imageView.setImageDrawable(new BitmapDrawable(getResources(), rotatedBitmap)); imageView.setScaleType( ScaleType.CENTER ); }

Cualquier ayuda sería muy apreciada, ya que no sé muy bien cómo proceder. Las "lecturas" que obtengo mientras lo intento es algo impreciso y apunta en la dirección incorrecta. ¿Estoy haciendo algo realmente diferente o solo tuve una prueba realmente mala?


Pasé cerca de 40 horas un fin de semana tratando de hacer esto.

Dolor en el trasero, con suerte puedo evitar ese dolor.

Ok, te lo advierto, este es un código feo. Estaba en apuros para terminarlo, no tiene esquemas de nomenclatura, pero traté de comentarlo lo mejor que pude por ti.

Se usó para ubicar grandes pilas de nueces en campos para almacenamiento

Utilizando la latitud y la longitud actuales del teléfono, el lat / lon del destino, el sensor de la brújula y algo de álgebra, pude calcular la dirección hasta el destino.

Las lecturas de Lat / lon y sensor se extraen de la clase MainApplication

Este es uno de los códigos de arrow.class, que usé para dibujar una flecha en un lienzo hacia una dirección.

//The location you want to go to// //"Given North" double lat=0; double lon=0; ////////////////////////////////// protected void onDraw(Canvas canvas) { //Sensor values from another class managing Sensor float[] v = MainApplication.getValues(); //The current location of the device, retrieved from another class managing GPS double ourlat= MainApplication.getLatitudeD(); double ourlon= MainApplication.getLongitudeD(); //Manually calculate the direction of the pile from the device double a= Math.abs((lon-ourlon)); double b= Math.abs((lat-ourlat)); //archtangent of a/b is equal to the angle of the device from 0-degrees in the first quadrant. (Think of a unit circle) double thetaprime= Math.atan(a/b); double theta= 0; //Determine the ''quadrant'' that the desired location is in //ASTC (All, Sin, Tan, Cos) Determines which value is positive //Gotta love Highschool algebra if((lat<ourlat)&&(lon>ourlon)){//-+ //theta is 180-thetaprime because it is in the 2nd quadrant theta= ((Math.PI)-thetaprime); //subtract theta from the compass value retrieved from the sensor to get our final direction theta=theta - Math.toRadians(v[0]); }else if((lat<ourlat)&&(lon<ourlon)){//-- //Add 180 degrees because it is in the third quadrant theta= ((Math.PI)+thetaprime); //subtract theta from the compass value retreived from the sensor to get our final direction theta=theta - Math.toRadians(v[0]); }else if((lat>ourlat)&&(lon>ourlon)){ //++ //No change is needed in the first quadrant theta= thetaprime; //subtract theta from the compass value retreived from the sensor to get our final direction theta=theta - Math.toRadians(v[0]); }else if((lat>ourlat)&&(lon<ourlon)){ //+- //Subtract thetaprime from 360 in the fourth quadrant theta= ((Math.PI*2)-thetaprime); //subtract theta from the compass value retreived from the sensor to get our final direction theta=theta - Math.toRadians(v[0]); } canvas.drawBitmap(_bitmap, 0, 0, paint); float[] results = {0}; //Store data Location.distanceBetween(ourlat, ourlon, lat, lon, results); try{ //Note, pileboundary is a value retreived from a database //This changes the color of the canvas based upon how close you are to the destination //Green < 100 (or database value), Yellow < (100)*2, Otherwise red if((results[0])<(pileboundary==0?100:pileboundary)){ _canvas.drawColor(Color.GREEN); }else if((results[0])<(pileboundary==0?100:pileboundary)*2){ _canvas.drawColor(Color.YELLOW); }else{ _canvas.drawColor(Color.rgb(0xff, 113, 116)); //RED-ish } //Draw the distance(in feet) from the destination canvas.drawText("Distance: "+Integer.toString((int) (results[0]*3.2808399))+ " Feet", 3, height-3, textpaint); }catch(IllegalArgumentException ex){ //im a sloppy coder } int w = canvas.getWidth(); int h = height; int x = w / 2; //put arrow in center int y = h / 2; canvas.translate(x, y); if (v != null) { // Finally, we rotate the canvas to the desired direction canvas.rotate((float)Math.toDegrees(theta)); } //Draw the arrow! canvas.drawPath(thearrow, paint); } //Some of my declarations, once again sorry :P GeomagneticField gf; Bitmap _bitmap; Canvas _canvas; int _height; int _width; Bitmap b; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //Get the current GeomagneticField (Should be valid until 2016, according to android docs) gf = new GeomagneticField((float)lat,(float)lon,(float)MainApplication.getAltitude(),System.currentTimeMillis()); _height = View.MeasureSpec.getSize(heightMeasureSpec); _width = View.MeasureSpec.getSize(widthMeasureSpec); setMeasuredDimension(_width, _height); _bitmap = Bitmap.createBitmap(_width, _height, Bitmap.Config.ARGB_8888); _canvas = new Canvas(_bitmap); b=Bitmap.createBitmap(_bitmap); drawBoard(); invalidate(); } //Here is the code to draw the arrow thearrow.moveTo(0, -50); thearrow.lineTo(-20, 50); thearrow.lineTo(0, 50); thearrow.lineTo(20, 50); thearrow.close(); thearrow.setFillType(FillType.EVEN_ODD);

Espero que puedas leer mi código ... Si tengo tiempo, lo voy a hacer un poco más bonito.

Si necesita alguna explicación, hágamelo saber.

-MrZander


Su función rotateImageView debería funcionar bien, sin embargo, hay algunas cosas que se deben cambiar en los cálculos de rotación.

//This is where we choose to point it float direction = azimuth + LocationObj.bearingTo( destinationObj ); rotateImageView( arrow, R.drawable.arrow, direction );

El problema es que bearingTo te dará un rango de -180 a 180, lo que confundirá un poco las cosas. Tendremos que convertir este valor en un rango de 0 a 360 para obtener la rotación correcta.

Esta es una tabla de lo que realmente queremos, en comparación con lo que bearingTo nos da

+-----------+--------------+ | bearingTo | Real bearing | +-----------+--------------+ | 0 | 0 | +-----------+--------------+ | 90 | 90 | +-----------+--------------+ | 180 | 180 | +-----------+--------------+ | -90 | 270 | +-----------+--------------+ | -135 | 225 | +-----------+--------------+ | -180 | 180 | +-----------+--------------+

Aunque el bearingTo está en el rango de -180 a 180, 0 sigue siendo verdadero al norte, lo que nos deja a este cálculo:

// Store the bearingTo in the bearTo variable float bearTo = LocationObj.bearingTo( destinationObj ); // If the bearTo is smaller than 0, add 360 to get the rotation clockwise. if (bearTo < 0) { bearTo = bearTo + 360; }

Si agregamos algunos valores ficticios para probar nuestra nueva fórmula:

float bearTo = -100; // This will now equal to true if (-100 < 0) { bearTo = -100 + 360 = 360 - 100 = 260; }

¡Ya hemos resuelto el rumbo A, vamos directo al azimut!

Debe restar la declinación en lugar de agregarla, ya que queremos que el acimut sea 0 cuando apuntemos el teléfono directamente al norte verdadero en lugar de agregar la declinación al azimut, lo que nos dará el doble de declinación cuando apuntemos el teléfono al verdadero norte. Corrija esto restando la declinación en lugar de agregarla.

azimuth -= geoField.getDeclination(); // converts magnetic north into true north

Cuando volteemos el teléfono hacia el norte verdadero ahora, el azimut será igual a 0

Su código para corregir el azimut ya no es necesario.

// Remove / uncomment this line azimuth = azimuth % 360;

Ahora continuaremos al punto donde calculamos la rotación real. Pero primero voy a resumir qué tipo de valores tenemos ahora y explicar lo que realmente son:

bearTo = El ángulo desde el norte verdadero hasta la ubicación de destino desde el punto donde estamos actualmente.

azimuth = El ángulo que ha girado su teléfono desde el norte verdadero.

Al decir esto, si apunta su teléfono directamente hacia el norte verdadero, realmente queremos que la flecha gire el ángulo al que se establece bearTo. Si apuntas tu teléfono a 45 grados del norte verdadero, queremos que la flecha gire 45 grados menos que lo que es TODO el oso. Esto nos deja a los siguientes cálculos:

float direction = bearTo - azimuth;

Sin embargo, si ponemos algunos valores ficticios: bearTo = 45; acimut = 180;

direction = 45 - 180 = -135;

Esto significa que la flecha debe rotar 135 grados en sentido contrario a las agujas del reloj. Tendremos que poner en una condición if similar si lo hiciéramos con bearTo!

// If the direction is smaller than 0, add 360 to get the rotation clockwise. if (direction < 0) { direction = direction + 360; }

Su texto de rumbo, el N, E, S y W está desactivado, por lo que los he corregido en el método final a continuación.

Su método onSensorChanged debería verse así:

public void onSensorChanged( SensorEvent event ) { // If we don''t have a Location, we break out if ( LocationObj == null ) return; float azimuth = event.values[0]; float baseAzimuth = azimuth; GeomagneticField geoField = new GeomagneticField( Double .valueOf( LocationObj.getLatitude() ).floatValue(), Double .valueOf( LocationObj.getLongitude() ).floatValue(), Double.valueOf( LocationObj.getAltitude() ).floatValue(), System.currentTimeMillis() ); azimuth -= geoField.getDeclination(); // converts magnetic north into true north // Store the bearingTo in the bearTo variable float bearTo = LocationObj.bearingTo( destinationObj ); // If the bearTo is smaller than 0, add 360 to get the rotation clockwise. if (bearTo < 0) { bearTo = bearTo + 360; } //This is where we choose to point it float direction = bearTo - azimuth; // If the direction is smaller than 0, add 360 to get the rotation clockwise. if (direction < 0) { direction = direction + 360; } rotateImageView( arrow, R.drawable.arrow, direction ); //Set the field String bearingText = "N"; if ( (360 >= baseAzimuth && baseAzimuth >= 337.5) || (0 <= baseAzimuth && baseAzimuth <= 22.5) ) bearingText = "N"; else if (baseAzimuth > 22.5 && baseAzimuth < 67.5) bearingText = "NE"; else if (baseAzimuth >= 67.5 && baseAzimuth <= 112.5) bearingText = "E"; else if (baseAzimuth > 112.5 && baseAzimuth < 157.5) bearingText = "SE"; else if (baseAzimuth >= 157.5 && baseAzimuth <= 202.5) bearingText = "S"; else if (baseAzimuth > 202.5 && baseAzimuth < 247.5) bearingText = "SW"; else if (baseAzimuth >= 247.5 && baseAzimuth <= 292.5) bearingText = "W"; else if (baseAzimuth > 292.5 && baseAzimuth < 337.5) bearingText = "NW"; else bearingText = "?"; fieldBearing.setText(bearingText); }