为什么省略号没有显示在我的处理代码中?

问题描述 投票:0回答:1

我对处理中的代码有疑问。我正在尝试显示过去几年的天气数据并在屏幕上绘制椭圆以创建图表。但是,椭圆并未被绘制。这可能是什么原因?坐标有效且在屏幕区域内。当我尝试在循环外部绘制具有简单坐标的椭圆时,它可以正常工作。这就是为什么我相信它与循环有关。我在这里分享了我的代码。由于 API 密钥无效,它可能无法执行,但也许有人仍然可以帮助我。

import http.requests.*;
import java.util.Calendar;


void setup()
{
  fullScreen();
  background(0);
  noStroke();
  
  
  Calendar calendar = Calendar.getInstance();
  
  int d;
  int m;
  int y;
  
  int cols = 8;
  int rows = 11;
  
  float[][] temps = new float[cols][rows];
  
  for(int i=0;i<8;i++)
  {
    calendar.add(Calendar.DAY_OF_YEAR, -1);
    m= calendar.get(Calendar.MONTH) + 1;
    d= calendar.get(Calendar.DAY_OF_MONTH);
    
    for (int p=0;p<11;p++)
    {
      calendar.add(Calendar.YEAR, -1);
      y = calendar.get(Calendar.YEAR);
      String todate = y+"-"+m+"-"+d;
      
      GetRequest get = new GetRequest("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Innsbruck/"+todate+"?unitGroup=metric&include=days&key=xxx&contentType=json");
      get.send();
      //println("Reponse Content: " + get.getContent());

      JSONObject response = parseJSONObject(get.getContent());
      float tempmax = response.getJSONArray("days").getJSONObject(0).getFloat("tempmax");
      //println(d+"."+m+"."+y+": Maxtemp - "+tempmax);
      
      temps[i][p]=tempmax;
      
      
      float pointx = width-width/10-width/10*i;
      float pointy = height/2+tempmax*10;
      
      println(pointx + ", " + pointy);
      fill(255);
      ellipse(pointx,pointy,5,5);
    }
  }
  
}

void draw()
{
  
}
java for-loop processing drawing ellipse
1个回答
0
投票

有几件事同时发生,将程序分解为更简单的步骤并一次解决一个问题会更容易。

例如:

  1. 您的代码正在使用 Visualcrossing Weather API。您使用
    xxx
    作为 API 密钥所在位置的占位符。在线共享代码时这完全没问题。您需要将该密钥保密:只需确保在本地运行代码时将 xxx 替换为实际的 Visualcrossing API 密钥即可。
  2. 您的代码使用两个嵌套的 for 循环,这将导致每次运行草图时立即发出 8 x 11 个请求。通常Web API有一个速率限制:你不能在很短的时间内多次调用它们。您可以将程序拆分为两个:一个请求 88 个天气数据点并将数据缓存到本地 .json 文件以供稍后使用;另一个请求 88 个天气数据点并将数据缓存到本地 .json 文件中以供稍后使用。一个草图,只需加载本地 .json 文件并根据您的需要可视化数据。 (这样您就不会被 API 阻止,并且您可以使用缓存数据迭代/尝试任意多个版本的可视化。) 尚不清楚您希望如何将数据映射到 API 并从 API 返回。也许
  3. i
  4. 循环(从 0 到 8)意味着 0 到 7 天,而
    p
    (从 0 到 11)代表月份,所以你会得到一周、一个月内每天的最高温度一次?对
    m
    存在混淆,因为您总是将其设置为
    m= calendar.get(Calendar.MONTH) + 1;
    ,因此该值永远不会改变:它将是当前月份 + 1(循环 8 次)。也许您的意思是
    m= calendar.get(Calendar.MONTH) + i;
    ? (类似地,
    p
    计数器不用于增加日期)。
    
    
  5. 以下是每个部分的一些希望有帮助的信息。

API 密钥错误

当我运行您的代码时,我在处理控制台中收到此错误: WARNING: Authentication error: Unable to respond to any of these challenges: {} java.lang.RuntimeException: A JSONObject text must begin with '{' at processing.data.JSONObject.<init>(JSONObject.java:255) at processing.data.JSONObject.<init>(JSONObject.java:239) at processing.core.PApplet.parseJSONObject(PApplet.java:5377) at sketch_231003b.setup(sketch_231003b.java:59) at processing.core.PApplet.handleDraw(PApplet.java:2051) at processing.awt.PSurfaceAWT$9.callDraw(PSurfaceAWT.java:1386) at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:356) NullPointerException

这仅意味着 
xxx

API 不正确,在您的代码中您需要使用实际的 API 密钥。 (请不要在网上公开分享)。

处理此问题的一种典型方法是将 API 密钥设置为环境变量(例如 

MY_API_KEY=#######

,然后在处理中使用

System.getenv('MY_API_KEY')
来检索值)。如果您不熟悉设置环境变量,请不要担心:现在对密钥进行硬编码就可以了。请小心与谁共享该代码:)

缓存数据

您已经在此处进行查询并解析响应:

GetRequest get = new GetRequest("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Innsbruck/"+todate+"?unitGroup=metric&include=days&key=xxx&contentType=json"); get.send(); JSONObject response = parseJSONObject(get.getContent());

您可以使用 
JSONArray

(

https://processing.org/reference/JSONArray.html
) 来存储数据。 这是一个基于您的代码的示例: import http.requests.*; import java.util.Calendar; void setup() { background(0); String API_KEY = "PLACE_YOUR_WEATHER_API_KEY_HERE"; // prepare JSONArray to cache Weather API data JSONArray weatherAPIData = new JSONArray(); // counter for each API call / data entry int weatherAPICounter = 0; Calendar calendar = Calendar.getInstance(); int d; int m; int y; int cols = 8; int rows = 11; int total = rows * cols; for(int i = 0; i < cols; i++) { calendar.add(Calendar.DAY_OF_YEAR, -1); m = calendar.get(Calendar.MONTH) + 1; d = calendar.get(Calendar.DAY_OF_MONTH); for (int p = 0; p < rows; p++) { calendar.add(Calendar.YEAR, -1); y = calendar.get(Calendar.YEAR); String todate = y+"-"+m+"-"+d; println("requesting", todate, weatherAPICounter+1, "of", total); GetRequest get = new GetRequest("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Innsbruck/" + todate + "?unitGroup=metric&include=days&key=" + API_KEY + "&contentType=json"); get.send(); println("Reponse Content: " + get.getContent()); JSONObject response = parseJSONObject(get.getContent()); // cache the API data into RAM weatherAPIData.setJSONObject(weatherAPICounter, response); // increment data counter weatherAPICounter++; // wait 1s in between calls (to avoid API rate limits) delay(1000); } } // persist the API data cache to disk saveJSONArray(weatherAPIData, "data/weather-api-data.json"); println("cached saved to the data folder"); exit(); }

如上所述,日期映射过程尚不清楚。目前它请求 API 似乎不支持的数据年份:

Reponse Content: Bad API Request:Invalid year requested. Years must be between 1950 and 2050 java.lang.RuntimeException: A JSONObject text must begin with '{' at processing.data.JSONObject.<init>(JSONObject.java:255) at processing.data.JSONObject.<init>(JSONObject.java:239) at processing.core.PApplet.parseJSONObject(PApplet.java:5377) at JSONAPICache.setup(JSONAPICache.java:61) at processing.core.PApplet.handleDraw(PApplet.java:2051) at processing.awt.PSurfaceAWT$9.callDraw(PSurfaceAWT.java:1386) at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:356)

获得此数据后,您可以编写一个单独的草图来加载它并根据映射的 
maxtemp

数据渲染椭圆。请记住将weather-api-data.json文件从上面的草图中拖放到新草图中:


void setup()
{
  fullScreen();
  background(0);
  noStroke();
  
  
  int cols = 8;
  int rows = 11;
  
  // load cached data
  JSONArray weatherAPIData = loadJSONArray("data/weather-api-data.json");
  // counter for each API call / data entry
  int weatherAPICounter = 0;
  
  
  for(int i = 0; i < cols; i++)
  {
    for (int p=0; p < rows; p++)
    {
      // try to get each request (and handle errors)
      try {
        
        JSONObject response = weatherAPIData.getJSONObject(weatherAPICounter);
        float tempmax = response.getJSONArray("days").getJSONObject(0).getFloat("tempmax");
        
        float pointx = width-width/10-width/10*i;
        float pointy = height/2+tempmax*10;
        
        println(pointx + ", " + pointy);
        fill(255);
        ellipse(pointx,pointy,5,5);
        
      
      } catch(Exception e){
        println("encountered null data index", weatherAPICounter);
        e.printStackTrace();
      }
      
      // increment JSONArray counter 
      weatherAPICounter++;
    }
  }
  
}

(您可能还会发现 
map()

(

https://processing.org/reference/map_.html
) 函数可以方便地重新映射 maxtemp 数据)。
祝调试顺利,并享受可视化数据的乐趣。

© www.soinside.com 2019 - 2024. All rights reserved.