ポリゴンの n 番目の内部リングを折れ線として戻します。リングは図形的方向付けによって編成されてはいません。内部の図形照合ルーチンで定義されている規則に従って編成されています。したがって、リングの順序を事前定義することはできません。
構文
ST_InteriorRingN(p ST_Polygon, n Integer)
戻りタイプ
db2gse.ST_LineString
例
南洋諸島で鳥の群生の調査を計画しているある鳥類学者は、特定の受動的な種類の鳥の採食地域は海岸線に限定されていることが分かっています。一部の島には湖が存在しています。そのような湖の湖岸は、より攻撃的な別の種類の鳥によって占領されています。それぞれの島について、湖の周囲の長さの合計がある一定の限界値を超えると、攻撃的な鳥の数が増えすぎて海岸に生息する受動的な種類の鳥の存続が脅かされることを、この鳥類学者は知っています。このため、この鳥類学者は島々の内部リングの周囲の長さの総和を知る必要があります。
図 34 で、島の外部リングはそれぞれの島と海との生態学的な境界を表しています。いくつかの島には湖があり、ポリゴンの内部リングとして表されています。
図 34. ST_InteriorRingN を用いて、それぞれの島の湖岸線の長さを判別する
ISLANDS 表の ID 列と name 列はそれぞれの島を識別し、 land ポリゴン列にはその島の図形が格納されています。
CREATE TABLE ISLANDS (id integer, name varchar(32), land db2gse.ST_Polygon);
以下の ODBC プログラムでは、ST_InteriorRingN 関数を使って、それぞれの島のポリゴンから内部リング (湖) を折れ線として抽出します。 length 関数によって戻される折れ線の周囲の長さを合計して、その島の ID とともに表示します。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "sg.h" #include "sgerr.h" #include "sqlcli1.h" /*** *** *** Change these constants *** *** ***/ #define USER_NAME "sdetest" /* your user name */ #define USER_PASS "acid.rain" /* your user password */ #define DB_NAME "mydb" /* database to connect to */ static void check_sql_err (SQLHDBC handle, SQLHSTMT hstmt, LONG rc, CHAR *str); void main( argc, argv ) int argc; char *argv[]; { SQLHDBC handle; SQLHENV henv; CHAR sql_stmt[256]; LONG rc, total_perimeter, num_lakes, lake_number, island_id, lake_perimeter; SQLHSTMT island_cursor, lake_cursor; SDWORD pcbvalue, id_ind, lake_ind, length_ind; /* Allocate memory for the ODBC environment handle henv and initialize the application. */ rc = SQLAllocEnv (&henv); if (rc != SQL_SUCCESS) { printf ("SQLAllocEnv failed with %d\n", rc); exit(0); } /* Allocate memory for a connection handle within the henv environment. */ rc = SQLAllocConnect (henv, &handle); if (rc != SQL_SUCCESS) { printf ("SQLAllocConnect failed with %d\n", rc); exit(0); } /* Load the ODBC driver and connect to the data source identified by the database, user, and password.*/ rc = SQLConnect (handle, (UCHAR *)DB_NAME, SQL_NTS, (UCHAR *)USER_NAME, SQL_NTS, (UCHAR *)USER_PASS, SQL_NTS); check_sql_err (handle, NULL, rc, "SQLConnect"); /* Allocate memory to the SQL statement handle island_cursor. */ rc = SQLAllocStmt (handle, &island_cursor); check_sql_err (handle, NULL, rc, "SQLAllocStmt"); /* Prepare and execute the query to get the island IDs and number of lakes (interior rings) */ strcpy (sql_stmt, "select id, db2gse.ST_NumInteriorRings(land) from ISLANDS"); rc = SQLExecDirect (island_cursor, (UCHAR *)sql_stmt, SQL_NTS); check_sql_err (NULL, island_cursor, rc, "SQLExecDirect"); /* Bind the island table's ID column to the variable island_id */ rc = SQLBindCol (island_cursor, 1, SQL_C_SLONG, &island_id, 0, &id_ind); check_sql_err (NULL, island_cursor, rc, "SQLBindCol"); /* Bind the result of numinteriorrings(land) to the num_lakes variable. */ rc = SQLBindCol (island_cursor, 2, SQL_C_SLONG, &num_lakes, 0, &lake_ind); check_sql_err (NULL, island_cursor, rc, "SQLBindCol"); /* Allocate memory to the SQL statement handle lake_cursor. */ rc = SQLAllocStmt (handle, &lake_cursor); check_sql_err (handle, NULL, rc, "SQLAllocStmt"); /* Prepare the query to get the length of an interior ring. */ strcpy (sql_stmt, "select Length(db2gse.ST_InteriorRingN(land, cast (? as integer))) from ISLANDS where id = ?"); rc = SQLPrepare (lake_cursor, (UCHAR *)sql_stmt, SQL_NTS); check_sql_err (NULL, lake_cursor, rc, "SQLPrepare"); /* Bind the lake_number variable as the first input parameter */ pcbvalue = 0; rc = SQLBindParameter (lake_cursor, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &lake_number, 0, &pcbvalue); check_sql_err (NULL, lake_cursor, rc, "SQLBindParameter"); /* Bind the island_id as the second input parameter */ pcbvalue = 0; rc = SQLBindParameter (lake_cursor, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &island_id, 0, &pcbvalue); check_sql_err (NULL, lake_cursor, rc, "SQLBindParameter"); /* Bind the result of the Length(db2gse.ST_InteriorRingN(land, cast (? as integer))) to the variable lake_perimeter */ rc = SQLBindCol (lake_cursor, 1, SQL_C_SLONG, &lake_perimeter, 0, &length_ind); check_sql_err (NULL, island_cursor, rc, "SQLBindCol"); /* Outer loop, get the island ids and the number of lakes (interior rings) */ while (SQL_SUCCESS == rc) { /* Fetch an island */ rc = SQLFetch (island_cursor); if (rc != SQL_NO_DATA) { check_sql_err (NULL, island_cursor, rc, "SQLFetch"); /* Inner loop, for this island, get the perimeter of all of its lakes (interior rings) */ for (total_perimeter = 0,lake_number = 1; lake_number <= num_lakes; lake_number++) { rc = SQLExecute (lake_cursor); check_sql_err (NULL, lake_cursor, rc, "SQLExecute"); rc = SQLFetch (lake_cursor); check_sql_err (NULL, lake_cursor, rc, "SQLFetch"); total_perimeter += lake_perimeter; SQLFreeStmt (lake_cursor, SQL_CLOSE); } } /* Display the Island id and the total perimeter of its lakes. */ printf ("Island ID = %d, Total lake perimeter = %d\n", island_id,total_perimeter); } SQLFreeStmt (lake_cursor, SQL_DROP); SQLFreeStmt (island_cursor, SQL_DROP); SQLDisconnect (handle); SQLFreeConnect (handle); SQLFreeEnv (henv); printf( "\nTest Complete ...\n" ); } static void check_sql_err (SQLHDBC handle, SQLHSTMT hstmt, LONG rc, CHAR *str) { SDWORD dbms_err = 0; SWORD length; UCHAR err_msg[SQL_MAX_MESSAGE_LENGTH], state[6]; if (rc != SQL_SUCCESS) { SQLError (SQL_NULL_HENV, handle, hstmt, state, &dbms_err, err_msg, SQL_MAX_MESSAGE_LENGTH - 1, &length); printf ("%s ERROR (%d): DBMS code:%d, SQL state: %s, message: \n %s\n", str, rc, dbms_err, state, err_msg); if (handle) { SQLDisconnect (handle); SQLFreeConnect (handle); } exit(1); } }