데이터 영역 요청

dataLayers 엔드포인트는 지정된 위치를 둘러싼 지역의 자세한 태양 정보 정보를 제공합니다. 엔드포인트는 다음을 포함하여 다운로드 가능한 TIFF 파일 17개를 반환합니다.

  • 디지털 표면 모델 (DSM)
  • RGB 복합 레이어 (항공 이미지)
  • 분석의 경계를 식별하는 마스크 레이어
  • 연간 태양 플럭스 또는 특정 표면의 연간 수확량
  • 월별 태양 플럭스 또는 특정 표면의 월별 수확량
  • 시간당 음영 (24시간)

Solar API에서 플럭스를 정의하는 방법에 관한 자세한 내용은 Solar API 개념을 참고하세요.

데이터 영역 요청 정보

다음 예는 dataLayers 메서드에 대한 REST 요청의 URL을 보여줍니다.

https://solar.googleapis.com/v1/dataLayers:get?parameters

다음을 지정하는 요청 URL 매개변수를 포함합니다.

  • 위치의 위도 및 경도 좌표
  • 위치를 둘러싼 지역의 반경
  • 반환할 데이터의 하위 집합 (DSM, RGB, 마스크, 연간 플럭스 또는 월간 플럭스)
  • 결과에서 허용되는 최소 품질
  • 반환할 최소 데이터 배율(미터/픽셀)

데이터 영역 요청 예시

다음 예에서는 위도 = 37.4450, 경도 = -122.1390의 좌표에 있는 위치의 반경 100m 내의 모든 건물 통계 정보를 요청합니다.

응답의 URL에 요청하려면 URL에 API 키를 추가합니다.

curl -X GET "https://solar.googleapis.com/v1/dataLayers:get?location.latitude=37.4450&location.longitude=-122.1390&radiusMeters=100&view=FULL_LAYERS&requiredQuality=HIGH&exactQualityRequired=true&pixelSizeMeters=0.5&key=YOUR_API_KEY"

cURL 요청의 URL을 브라우저의 URL 표시줄에 붙여넣어 HTTP 요청을 실행할 수도 있습니다. API 키를 전달하면 사용 및 분석 기능이 개선되고 응답 데이터에 대한 액세스 제어가 개선됩니다.

참고: 이 형식은 테스트 환경 전용입니다. 자세한 내용은 OAuth 사용을 참고하세요.

응답의 URL을 요청하려면 결제 프로젝트 이름과 OAuth 토큰을 전달합니다.

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "X-Goog-User-Project: PROJECT_NUMBER_OR_ID" \
  "https://solar.googleapis.com/v1/dataLayers:get?location.latitude=37.4450&location.longitude=-122.1390&radius_meters=100&required_quality=HIGH&exactQualityRequired=true"
        

응답의 URL에 요청하려면 요청에 API 키 또는 OAuth 토큰을 포함하세요. 다음 예에서는 API 키를 사용합니다.

/**
 * Fetches the data layers information from the Solar API.
 *   https://developers.google.com/maps/documentation/solar/data-layers
 *
 * @param  {LatLng} location      Point of interest as latitude longitude.
 * @param  {number} radiusMeters  Radius of the data layer size in meters.
 * @param  {string} apiKey        Google Cloud API key.
 * @return {Promise<DataLayersResponse>}  Data Layers response.
 */
export async function getDataLayerUrls(
  location: LatLng,
  radiusMeters: number,
  apiKey: string,
): Promise<DataLayersResponse> {
  const args = {
    'location.latitude': location.latitude.toFixed(5),
    'location.longitude': location.longitude.toFixed(5),
    radius_meters: radiusMeters.toString(),
    // The Solar API always returns the highest quality imagery available.
    // By default the API asks for HIGH quality, which means that HIGH quality isn't available,
    // but there is an existing MEDIUM or LOW quality, it won't return anything.
    // Here we ask for *at least* LOW quality, but if there's a higher quality available,
    // the Solar API will return us the highest quality available.
    required_quality: 'LOW',
  };
  console.log('GET dataLayers\n', args);
  const params = new URLSearchParams({ ...args, key: apiKey });
  // https://developers.google.com/maps/documentation/solar/reference/rest/v1/dataLayers/get
  return fetch(`https://solar.googleapis.com/v1/dataLayers:get?${params}`).then(
    async (response) => {
      const content = await response.json();
      if (response.status != 200) {
        console.error('getDataLayerUrls\n', content);
        throw content;
      }
      console.log('dataLayersResponse', content);
      return content;
    },
  );
}

필드 및 데이터 유형은 TypeScript에서 '유형'입니다. 이 예에서는 응답에 관심 있는 필드(예: 픽셀 값, 위도/경도 경계 상자)를 저장하는 맞춤 유형을 정의합니다. 원하는 대로 더 많은 필드를 포함할 수 있습니다.

export interface GeoTiff {
  width: number;
  height: number;
  rasters: Array<number>[];
  bounds: Bounds;
}

지원되는 데이터 유형은 다음과 같습니다.

export interface DataLayersResponse {
  imageryDate: Date;
  imageryProcessedDate: Date;
  dsmUrl: string;
  rgbUrl: string;
  maskUrl: string;
  annualFluxUrl: string;
  monthlyFluxUrl: string;
  hourlyShadeUrls: string[];
  imageryQuality: 'HIGH' | 'MEDIUM' | 'LOW';
}

export interface Bounds {
  north: number;
  south: number;
  east: number;
  west: number;
}

// https://developers.google.com/maps/documentation/solar/reference/rest/v1/buildingInsights/findClosest
export interface BuildingInsightsResponse {
  name: string;
  center: LatLng;
  boundingBox: LatLngBox;
  imageryDate: Date;
  imageryProcessedDate: Date;
  postalCode: string;
  administrativeArea: string;
  statisticalArea: string;
  regionCode: string;
  solarPotential: SolarPotential;
  imageryQuality: 'HIGH' | 'MEDIUM' | 'LOW';
}

export interface SolarPotential {
  maxArrayPanelsCount: number;
  panelCapacityWatts: number;
  panelHeightMeters: number;
  panelWidthMeters: number;
  panelLifetimeYears: number;
  maxArrayAreaMeters2: number;
  maxSunshineHoursPerYear: number;
  carbonOffsetFactorKgPerMwh: number;
  wholeRoofStats: SizeAndSunshineStats;
  buildingStats: SizeAndSunshineStats;
  roofSegmentStats: RoofSegmentSizeAndSunshineStats[];
  solarPanels: SolarPanel[];
  solarPanelConfigs: SolarPanelConfig[];
  financialAnalyses: object;
}

export interface SizeAndSunshineStats {
  areaMeters2: number;
  sunshineQuantiles: number[];
  groundAreaMeters2: number;
}

export interface RoofSegmentSizeAndSunshineStats {
  pitchDegrees: number;
  azimuthDegrees: number;
  stats: SizeAndSunshineStats;
  center: LatLng;
  boundingBox: LatLngBox;
  planeHeightAtCenterMeters: number;
}

export interface SolarPanel {
  center: LatLng;
  orientation: 'LANDSCAPE' | 'PORTRAIT';
  segmentIndex: number;
  yearlyEnergyDcKwh: number;
}

export interface SolarPanelConfig {
  panelsCount: number;
  yearlyEnergyDcKwh: number;
  roofSegmentSummaries: RoofSegmentSummary[];
}

export interface RoofSegmentSummary {
  pitchDegrees: number;
  azimuthDegrees: number;
  panelsCount: number;
  yearlyEnergyDcKwh: number;
  segmentIndex: number;
}

export interface LatLng {
  latitude: number;
  longitude: number;
}

export interface LatLngBox {
  sw: LatLng;
  ne: LatLng;
}

export interface Date {
  year: number;
  month: number;
  day: number;
}

export interface RequestError {
  error: {
    code: number;
    message: string;
    status: string;
  };
}

API는 다음 형식의 URL을 반환합니다.

https://solar.googleapis.com/v1/solar/geoTiff:get?id=HASHED_ID

이러한 URL은 요청된 데이터가 포함된 GeoTIFF 파일에 액세스하는 데 사용할 수 있습니다.

응답 예

요청은 다음과 같은 형식의 JSON 응답을 생성합니다.

{
  "imageryDate": {
    "year": 2022,
    "month": 4,
    "day": 6
  },
  "imageryProcessedDate": {
    "year": 2023,
    "month": 8,
    "day": 4
  },
  "dsmUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=MmQyMzI0NTMyZDc3YjBjNmQ3OTgyM2ZhNzMyNzk5NjItN2ZjODJlOThkNmQ5ZDdmZDFlNWU3MDY4YWFlMWU0ZGQ6UkdCOkhJR0g=",
  "rgbUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=NzQwNGQ0NmUyMzAzYWRiNmMxNzMwZTJhN2IxMTc4NDctOTI5YTNkZTlkM2MzYjRiNjE4MGNkODVmNjNiNDhkMzE6UkdCOkhJR0g=",
  "maskUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=ZTk1YTBlZmY5Y2FhMThlNWYzMWEzZGZhYzEzMGQzOTAtM2Q4NmUyMmM5ZThjZmE0YjhhZWMwN2UzYzdmYmQ3ZjI6TUFTSzpISUdI",
  "annualFluxUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=OTE0OWIxZDM3NmNlYjkzMWY2YjQyYjY5Y2RkYzNiOTAtZjU5YTVjZGQ3MzE3ZTQ4NTNmN2M4ZmY2MWZlZGZkMzg6QU5OVUFMX0ZMVVg6SElHSA==",
  "monthlyFluxUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=Y2NhOGRhOWI2MjVmYmNiZTY3Njk4Yjk0MGJhNTk1NDUtY2MyYTI4NDJmN2Q5YTI0MmY2NDQyZGUwZWJkMWQ0ZDg6TU9OVEhMWV9GTFVYOkhJR0g=",
  "hourlyShadeUrls": [
    "https://solar.googleapis.com/v1/geoTiff:get?id=OWFhOTZmNDU2OGQyNTYxYWQ4YjZkYjQ5NWI4Zjg1ODItZGEwNDNhMmM3NDU0MTY2OGIzZDY2OGU1NTY0NTFlMzE6TU9OVEhMWV9GTFVYOkhJR0g=",
    "https://solar.googleapis.com/v1/geoTiff:get?id=MTI1ZTI2YzM1ZTRlYjA3ZDM4NWE2ODY4MjUzZmIxZTMtNTRmYTI3YmQyYzVjZDcyYjc5ZTlmMTRjZjBmYTk4OTk6TU9OVEhMWV9GTFVYOkhJR0g=",
    ...
  ],
  "imageryQuality": "HIGH"
}

응답 데이터 액세스

응답 URL을 통해 데이터에 액세스하려면 추가 인증이 필요합니다. 인증 키를 사용하는 경우 API 키를 URL에 추가해야 합니다. OAuth 인증을 사용하는 경우 OAuth 헤더를 추가해야 합니다.

응답의 URL에 요청하려면 URL에 API 키를 추가합니다.

curl -X GET "https://solar.googleapis.com/v1/solar/geoTiff:get?id=fbde33e9cd16d5fd10d19a19dc580bc1-8614f599c5c264553f821cd034d5cf32&key=YOUR_API_KEY"

cURL 요청의 URL을 브라우저의 URL 표시줄에 붙여넣어 HTTP 요청을 실행할 수도 있습니다. API 키를 전달하면 사용 및 분석 기능이 개선되고 응답 데이터에 대한 액세스 제어가 개선됩니다.

응답의 URL을 요청하려면 결제 프로젝트 이름과 OAuth 토큰을 전달합니다.

curl -X GET \
-H 'X-Goog-User-Project: PROJECT_NUMBER_OR_ID' \
-H "Authorization: Bearer $TOKEN" \
"https://solar.googleapis.com/v1/solar/geoTiff:get?id=fbde33e9cd16d5fd10d19a19dc580bc1-8614f599c5c264553f821cd034d5cf32"
        

다음 예에서는 픽셀 데이터 값 (디지털 이미지의 개별 픽셀에 저장된 정보로 색상 값 및 기타 속성 포함)을 가져오고, GeoTIFF에서 위도와 경도를 계산하고, TypeScript 객체에 저장하는 방법을 보여줍니다.

이 특정 예에서는 유형 오류를 줄이고 코드의 안정성을 높이며 유지 관리를 쉽게 하는 유형 검사를 허용하도록 선택했습니다.

// npm install geotiff geotiff-geokeys-to-proj4 proj4

import * as geotiff from 'geotiff';
import * as geokeysToProj4 from 'geotiff-geokeys-to-proj4';
import proj4 from 'proj4';

/**
 * Downloads the pixel values for a Data Layer URL from the Solar API.
 *
 * @param  {string} url        URL from the Data Layers response.
 * @param  {string} apiKey     Google Cloud API key.
 * @return {Promise<GeoTiff>}  Pixel values with shape and lat/lon bounds.
 */
export async function downloadGeoTIFF(url: string, apiKey: string): Promise<GeoTiff> {
  console.log(`Downloading data layer: ${url}`);

  // Include your Google Cloud API key in the Data Layers URL.
  const solarUrl = url.includes('solar.googleapis.com') ? url + `&key=${apiKey}` : url;
  const response = await fetch(solarUrl);
  if (response.status != 200) {
    const error = await response.json();
    console.error(`downloadGeoTIFF failed: ${url}\n`, error);
    throw error;
  }

  // Get the GeoTIFF rasters, which are the pixel values for each band.
  const arrayBuffer = await response.arrayBuffer();
  const tiff = await geotiff.fromArrayBuffer(arrayBuffer);
  const image = await tiff.getImage();
  const rasters = await image.readRasters();

  // Reproject the bounding box into lat/lon coordinates.
  const geoKeys = image.getGeoKeys();
  const projObj = geokeysToProj4.toProj4(geoKeys);
  const projection = proj4(projObj.proj4, 'WGS84');
  const box = image.getBoundingBox();
  const sw = projection.forward({
    x: box[0] * projObj.coordinatesConversionParameters.x,
    y: box[1] * projObj.coordinatesConversionParameters.y,
  });
  const ne = projection.forward({
    x: box[2] * projObj.coordinatesConversionParameters.x,
    y: box[3] * projObj.coordinatesConversionParameters.y,
  });

  return {
    // Width and height of the data layer image in pixels.
    // Used to know the row and column since Javascript
    // stores the values as flat arrays.
    width: rasters.width,
    height: rasters.height,
    // Each raster reprents the pixel values of each band.
    // We convert them from `geotiff.TypedArray`s into plain
    // Javascript arrays to make them easier to process.
    rasters: [...Array(rasters.length).keys()].map((i) =>
      Array.from(rasters[i] as geotiff.TypedArray),
    ),
    // The bounding box as a lat/lon rectangle.
    bounds: {
      north: ne.y,
      south: sw.y,
      east: ne.x,
      west: sw.x,
    },
  };
}

RGB 레이어를 제외한 모든 TIFF 파일은 이미지 뷰어 애플리케이션에서 빈 이미지로 표시됩니다. 다운로드한 TIFF 파일을 보려면 QGIS와 같은 매핑 애플리케이션 소프트웨어로 가져옵니다.

이 요청 및 응답의 전체 사양은 참조 문서에 나와 있습니다.