From bde2b51f54b3b8ad597095a2a92e8ea5fcb5b091 Mon Sep 17 00:00:00 2001
From: "ram@mysql.r18.ru" <>
Date: Wed, 26 Feb 2003 19:13:01 +0400
Subject: [PATCH] Added num_geometries() and geometry_n() methods for MultiX
 geometry objects.

---
 sql/spatial.cc | 107 +++++++++++++++++++++++++++++++++++++++++++++++++
 sql/spatial.h  |  10 +++--
 2 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/sql/spatial.cc b/sql/spatial.cc
index 42dd74a697a..171716df061 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -845,6 +845,30 @@ int GMultiPoint::get_mbr(MBR *mbr) const
   return 0;
 }
 
+int GMultiPoint::num_geometries(uint32 *num) const
+{
+  *num = uint4korr(m_data);
+  return 0;
+}
+
+int GMultiPoint::geometry_n(uint32 num, String *result) const
+{
+  const char *data= m_data;
+  uint32 n_points;
+  if (no_data(data, 4))
+    return 1;
+  n_points= uint4korr(data);
+  data+= 4;
+  if ((num > n_points) || (num < 1))
+    return -1;
+  data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
+  if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
+    return 1;
+  result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
+
+  return 0;
+}
+
 /***************************** MultiLineString *******************************/
 
 size_t GMultiLineString::get_data_size() const 
@@ -970,6 +994,44 @@ int GMultiLineString::get_mbr(MBR *mbr) const
   return 0;
 }
 
+int GMultiLineString::num_geometries(uint32 *num) const
+{
+  *num = uint4korr(m_data);
+  return 0;
+}
+
+int GMultiLineString::geometry_n(uint32 num, String *result) const
+{
+  uint32 n_line_strings;
+  const char *data= m_data;
+  if (no_data(data, 4))
+    return 1;
+  n_line_strings= uint4korr(data);
+  data+= 4;
+
+  if ((num > n_line_strings) || (num < 1))
+    return -1;
+ 
+  for (; num > 0; --num)
+  {
+    if (no_data(data, WKB_HEADER_SIZE + 4))
+      return 1;
+    uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
+    if (num == 1)
+    {
+      if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points))
+	return 1;
+      result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
+      break;
+    }
+    else
+    {
+      data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
+    }
+  }
+  return 0;
+}
+
 int GMultiLineString::length(double *len) const
 {
   uint32 n_line_strings;
@@ -1164,6 +1226,51 @@ int GMultiPolygon::get_mbr(MBR *mbr) const
   return 0;
 }
 
+int GMultiPolygon::num_geometries(uint32 *num) const
+{
+  *num = uint4korr(m_data);
+  return 0;
+}
+
+int GMultiPolygon::geometry_n(uint32 num, String *result) const
+{
+  uint32 n_polygons;
+  const char *data= m_data, *polygon_n;
+  LINT_INIT(polygon_n);
+  if (no_data(data, 4))
+    return 1;
+  n_polygons= uint4korr(data);
+  data+= 4;
+
+  if ((num > n_polygons) || (num < 1))
+    return -1;
+
+  for (; num > 0; --num)
+  {
+    if (no_data(data, WKB_HEADER_SIZE + 4))
+      return 1;
+    uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
+
+    if (num == 1)
+      polygon_n= data;
+    data+= WKB_HEADER_SIZE + 4;
+    for (; n_linear_rings > 0; --n_linear_rings)
+    {
+      if (no_data(data, 4))
+	return 1;
+      uint32 n_points= uint4korr(data);
+      data+= 4 + POINT_DATA_SIZE * n_points;
+    }
+    if (num == 1)
+    {
+      if (result->reserve(data - polygon_n))
+	return -1;
+       result->q_append(polygon_n, data - polygon_n);
+      break;
+    }
+  }
+  return 0;
+}
 
 int GMultiPolygon::area(double *ar) const
 {
diff --git a/sql/spatial.h b/sql/spatial.h
index 3f09e86e823..15e4f7353ed 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -413,7 +413,6 @@ class GLineString: public Geometry
   int end_point(String *point) const;
   int point_n(uint32 n, String *result) const;
   int dimension(uint32 *dim) const { *dim = 1; return 0; }
-//  IsRing
 };
 
 /***************************** Polygon *******************************/
@@ -433,7 +432,6 @@ class GPolygon: public Geometry
   int centroid_xy(double *x, double *y) const;
   int centroid(String *result) const;
   int dimension(uint32 *dim) const { *dim = 2; return 0; }
-//  PointOnSurface
 };
 
 /***************************** MultiPoint *******************************/
@@ -445,6 +443,9 @@ class GMultiPoint: public Geometry
   int init_from_text(GTextReadStream *trs, String *wkb);
   int get_data_as_text(String *txt) const;
   int get_mbr(MBR *mbr) const;
+
+  int num_geometries(uint32 *num) const;
+  int geometry_n(uint32 num, String *result) const;
   int dimension(uint32 *dim) const { *dim = 0; return 0; }
 };
 
@@ -458,6 +459,8 @@ class GMultiLineString: public Geometry
   int get_data_as_text(String *txt) const;
   int get_mbr(MBR *mbr) const;
 
+  int num_geometries(uint32 *num) const;
+  int geometry_n(uint32 num, String *result) const;
   int length(double *len) const;
   int is_closed(int *closed) const;
   int dimension(uint32 *dim) const { *dim = 1; return 0; }
@@ -473,10 +476,11 @@ class GMultiPolygon: public Geometry
   int get_data_as_text(String *txt) const;
   int get_mbr(MBR *mbr) const;
 
+  int num_geometries(uint32 *num) const;
+  int geometry_n(uint32 num, String *result) const;
   int area(double *ar) const;
   int centroid(String *result) const;
   int dimension(uint32 *dim) const { *dim = 2; return 0; }
-//  PointOnSurface
 };
 
 /***************************** GeometryCollection *******************************/
-- 
2.30.9