2008-09-09 30 views
5

¿Alguien tiene un algoritmo decente para calcular los mínimos y máximos del eje?Algoritmo de gráfico (gráfico)

Al crear una tabla para un determinado conjunto de elementos de datos, me gustaría ser capaz de dar el algoritmo:

  • el valor máximo (y) en el conjunto
  • al mínimo (y) valor en el conjunto
  • el número de marcas de graduación para aparecer en el eje
  • un valor opcional que debe aparecer como una garrapata (por ejemplo, cero cuando mostrando + ve y valores -ve)

El algoritmo debe devolver

  • el valor del eje más grande
  • el valor más pequeño eje (aunque que podía deducirse de la más grande, el tamaño de intervalo y el número de garrapatas)
  • el tamaño del intervalo

Las marcas deben estar en un intervalo regular deben ser de un tamaño "razonable" (por ejemplo, 1, 3, 5, posiblemente incluso 2.5, pero no más sig higos).

La presencia del valor opcional sesgará esto, pero sin ese valor, el elemento más grande debería aparecer entre las dos marcas superiores, el valor más bajo entre las dos inferiores.

Ésta es una cuestión independiente del idioma, pero si hay una biblioteca de C#/NET alrededor, que sería sensacional;).

+0

Véase también http://stackoverflow.com/questions/361681/algorithm-for-nice-grid-line-intervals-on-a-graph y http://stackoverflow.com/questions/237220/ tickmark-algorithm-for-a-graph-axis –

Respuesta

0

He estado usando la biblioteca jQuery gráfico flot. Es de código abierto y hace bastante bien la generación de ejes/tics. Sugeriría mirar su código y pellizcar algunas ideas desde allí.

0

puedo recomendar lo siguiente:

  • Establecer un número mínimo atractivo a la vista de las principales líneas. Esto dependerá de la naturaleza de los datos que está presentando y del tamaño de la trama que está haciendo, pero 7 es un número bastante bueno
  • Elija el exponente y el multiplicador según una progresión de 1, 2, 5, 10, etc. que le dará al menos el número mínimo de líneas principales. (es decir, (máx. mín.)/(escala x 10^exponente)> = mín ._tick_marks)
  • Encuentra el múltiplo entero mínimo de tu exponente y multiplicador que se ajusta dentro de tu rango. Esta será la primera señal importante. El resto de los ticks se derivan de esto.

Esto se utilizó para una aplicación que permitía escalar arbitrariamente los datos y parecía funcionar bien.

2

OK, esto es lo que se me ocurrió para una de nuestras aplicaciones. Tenga en cuenta que no se trata del escenario de "valor opcional" que menciona, ya que nuestro valor opcional siempre es 0, pero no debería ser difícil para usted modificarlo.

Los datos se agregan continuamente a la serie, por lo que mantenemos el rango de valores y actualizado al inspeccionar cada punto de datos como su agregado; esto es muy económico y fácil de seguir.Los valores mínimos y máximos iguales son encasillados especiales: un espaciado de 0 indica que no se deben dibujar marcadores.

Esta solución no es diferente a la sugerencia de Andrew anterior, excepto que trata, de una manera ligeramente kludgy con algunas fracciones arbitrarias del multiplicador de exponente.

Por último, esta muestra está en C#. Espero eso ayude.

private float GetYMarkerSpacing() 
    { 
     YValueRange range = m_ScrollableCanvas. 
        TimelineCanvas.DataModel.CurrentYRange; 
     if (range.RealMinimum == range.RealMaximum) 
     { 
      return 0; 
     } 

     float absolute = Math.Max(
        Math.Abs(range.RealMinimum), 
        Math.Abs(range.RealMaximum)), 
      spacing  = 0; 
     for (int power = 0; power < 39; ++power) 
     { 
      float temp = (float) Math.Pow(10, power); 
      if (temp <= absolute) 
      { 
       spacing = temp; 
      } 
      else if (temp/2 <= absolute) 
      { 
       spacing = temp/2; 
       break; 
      } 
      else if (temp/2.5 <= absolute) 
      { 
       spacing = temp/2.5F; 
       break; 
      } 
      else if (temp/4 <= absolute) 
      { 
       spacing = temp/4; 
       break; 
      } 
      else if (temp/5 <= absolute) 
      { 
       spacing = temp/5; 
       break; 
      } 
      else 
      { 
       break; 
      } 
     } 

     return spacing; 
    } 
Cuestiones relacionadas