以线条形式返回多边形的第 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); } }