Class: TG::Geometry::Geom

Inherits:
Object
  • Object
show all
Defined in:
lib/tg/geometry.rb,
ext/tg_geometry/tg_geometry_ext.c

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.line_string(points, index: :natural, srid: nil) ⇒ TG::Geometry::Geom

Parameters:

  • points (Array<Array<Float>>)
  • index (:default, :none, :natural, :ystripes) (defaults to: :natural)
  • srid (Integer, nil) (defaults to: nil)

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tg/geometry.rb', line 42

class Geom
  # @!method srid
  #   @return [Integer, nil] SRID metadata; not used for reprojection
  #
  # @!method distance_to_lnglat_meters(lng, lat)
  #   Approximate meters in a query-local equirectangular frame. Not geodesy.
  #   @return [Float]
  #
  # @!method boundary_distance_to_lnglat_meters(lng, lat)
  #   Approximate meters to nearest boundary/segment/point.
  #   @return [Float]
  #
  # @!method nearest_point_lnglat(lng, lat)
  #   Raw planar nearest boundary/geometry point. Longitude is not wrapped.
  #   @return [Array(Float, Float)]
  #
  # @!method distance_to_xy(x, y)
  #   Planar distance in input coordinate units.
  #   @return [Float]
  #
  # @!method boundary_distance_to_xy(x, y)
  #   Planar boundary distance in input coordinate units.
  #   @return [Float]
  #
  # @!method nearest_point_xy(x, y)
  #   Planar nearest boundary/geometry point in input coordinate units.
  #   @return [Array(Float, Float)]
  #
  # @!method to_ewkb(srid: nil)
  #   Writes EWKB with the SRID flag set. Uses explicit srid: when provided,
  #   otherwise Geom#srid. Raises if no SRID is available. to_wkb remains plain.
  #   @return [String] frozen ASCII-8BIT EWKB string
end

.multi_polygon(polygons, index: :ystripes, srid: nil) ⇒ TG::Geometry::Geom

Each polygon is a Hash with :exterior and optional :holes, or an Array shorthand for an exterior with no holes.

Parameters:

  • polygons (Array<Hash, Array>)

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tg/geometry.rb', line 42

class Geom
  # @!method srid
  #   @return [Integer, nil] SRID metadata; not used for reprojection
  #
  # @!method distance_to_lnglat_meters(lng, lat)
  #   Approximate meters in a query-local equirectangular frame. Not geodesy.
  #   @return [Float]
  #
  # @!method boundary_distance_to_lnglat_meters(lng, lat)
  #   Approximate meters to nearest boundary/segment/point.
  #   @return [Float]
  #
  # @!method nearest_point_lnglat(lng, lat)
  #   Raw planar nearest boundary/geometry point. Longitude is not wrapped.
  #   @return [Array(Float, Float)]
  #
  # @!method distance_to_xy(x, y)
  #   Planar distance in input coordinate units.
  #   @return [Float]
  #
  # @!method boundary_distance_to_xy(x, y)
  #   Planar boundary distance in input coordinate units.
  #   @return [Float]
  #
  # @!method nearest_point_xy(x, y)
  #   Planar nearest boundary/geometry point in input coordinate units.
  #   @return [Array(Float, Float)]
  #
  # @!method to_ewkb(srid: nil)
  #   Writes EWKB with the SRID flag set. Uses explicit srid: when provided,
  #   otherwise Geom#srid. Raises if no SRID is available. to_wkb remains plain.
  #   @return [String] frozen ASCII-8BIT EWKB string
end

.parse_hex(hex, index: :ystripes) ⇒ TG::Geometry::Geom

Parses HEXWKB or HEXEWKB. SRID is preserved when the EWKB SRID flag is set.

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tg/geometry.rb', line 42

class Geom
  # @!method srid
  #   @return [Integer, nil] SRID metadata; not used for reprojection
  #
  # @!method distance_to_lnglat_meters(lng, lat)
  #   Approximate meters in a query-local equirectangular frame. Not geodesy.
  #   @return [Float]
  #
  # @!method boundary_distance_to_lnglat_meters(lng, lat)
  #   Approximate meters to nearest boundary/segment/point.
  #   @return [Float]
  #
  # @!method nearest_point_lnglat(lng, lat)
  #   Raw planar nearest boundary/geometry point. Longitude is not wrapped.
  #   @return [Array(Float, Float)]
  #
  # @!method distance_to_xy(x, y)
  #   Planar distance in input coordinate units.
  #   @return [Float]
  #
  # @!method boundary_distance_to_xy(x, y)
  #   Planar boundary distance in input coordinate units.
  #   @return [Float]
  #
  # @!method nearest_point_xy(x, y)
  #   Planar nearest boundary/geometry point in input coordinate units.
  #   @return [Array(Float, Float)]
  #
  # @!method to_ewkb(srid: nil)
  #   Writes EWKB with the SRID flag set. Uses explicit srid: when provided,
  #   otherwise Geom#srid. Raises if no SRID is available. to_wkb remains plain.
  #   @return [String] frozen ASCII-8BIT EWKB string
end

.parse_wkb(bytes, index: :ystripes) ⇒ TG::Geometry::Geom

Parses WKB or EWKB. SRID is preserved when the EWKB SRID flag is set.

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tg/geometry.rb', line 42

class Geom
  # @!method srid
  #   @return [Integer, nil] SRID metadata; not used for reprojection
  #
  # @!method distance_to_lnglat_meters(lng, lat)
  #   Approximate meters in a query-local equirectangular frame. Not geodesy.
  #   @return [Float]
  #
  # @!method boundary_distance_to_lnglat_meters(lng, lat)
  #   Approximate meters to nearest boundary/segment/point.
  #   @return [Float]
  #
  # @!method nearest_point_lnglat(lng, lat)
  #   Raw planar nearest boundary/geometry point. Longitude is not wrapped.
  #   @return [Array(Float, Float)]
  #
  # @!method distance_to_xy(x, y)
  #   Planar distance in input coordinate units.
  #   @return [Float]
  #
  # @!method boundary_distance_to_xy(x, y)
  #   Planar boundary distance in input coordinate units.
  #   @return [Float]
  #
  # @!method nearest_point_xy(x, y)
  #   Planar nearest boundary/geometry point in input coordinate units.
  #   @return [Array(Float, Float)]
  #
  # @!method to_ewkb(srid: nil)
  #   Writes EWKB with the SRID flag set. Uses explicit srid: when provided,
  #   otherwise Geom#srid. Raises if no SRID is available. to_wkb remains plain.
  #   @return [String] frozen ASCII-8BIT EWKB string
end

.polygon(exterior, holes: [], index: :ystripes, srid: nil) ⇒ TG::Geometry::Geom

Parameters:

  • exterior (Array<Array<Float>>)
  • holes (Array<Array<Array<Float>>>) (defaults to: [])
  • index (:default, :none, :natural, :ystripes) (defaults to: :ystripes)
  • srid (Integer, nil) (defaults to: nil)

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tg/geometry.rb', line 42

class Geom
  # @!method srid
  #   @return [Integer, nil] SRID metadata; not used for reprojection
  #
  # @!method distance_to_lnglat_meters(lng, lat)
  #   Approximate meters in a query-local equirectangular frame. Not geodesy.
  #   @return [Float]
  #
  # @!method boundary_distance_to_lnglat_meters(lng, lat)
  #   Approximate meters to nearest boundary/segment/point.
  #   @return [Float]
  #
  # @!method nearest_point_lnglat(lng, lat)
  #   Raw planar nearest boundary/geometry point. Longitude is not wrapped.
  #   @return [Array(Float, Float)]
  #
  # @!method distance_to_xy(x, y)
  #   Planar distance in input coordinate units.
  #   @return [Float]
  #
  # @!method boundary_distance_to_xy(x, y)
  #   Planar boundary distance in input coordinate units.
  #   @return [Float]
  #
  # @!method nearest_point_xy(x, y)
  #   Planar nearest boundary/geometry point in input coordinate units.
  #   @return [Array(Float, Float)]
  #
  # @!method to_ewkb(srid: nil)
  #   Writes EWKB with the SRID flag set. Uses explicit srid: when provided,
  #   otherwise Geom#srid. Raises if no SRID is available. to_wkb remains plain.
  #   @return [String] frozen ASCII-8BIT EWKB string
end

Instance Method Details

#bboxObject



1995
1996
1997
1998
# File 'ext/tg_geometry/tg_geometry_ext.c', line 1995

static VALUE rb_tg_geometry_geom_bbox(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return rect_from_tg_rect(tg_geom_rect(w->geom));
}

#boundary_distance_to_lnglat_meters(*args) ⇒ Object



3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3409

static VALUE rb_tg_geometry_geom_boundary_distance_to_lnglat_meters(int argc, VALUE *argv,
                                                                    VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE lng_value, lat_value;
    tg_distance_metric_t metric;
    double lng;
    double lat;

    tg_distance_parse_two_no_keywords(argc, argv, &lng_value, &lat_value);
    lng = tg_distance_lng_value(lng_value);
    lat = tg_distance_lat_value(lat_value);

    tg_distance_metric_lnglat(&metric, lng, lat);
    return rb_float_new(tg_boundary_distance_to_geom(w->geom, &metric));
}

#boundary_distance_to_xy(*args) ⇒ Object



3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3362

static VALUE rb_tg_geometry_geom_boundary_distance_to_xy(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE x_value, y_value;
    tg_distance_metric_t metric;
    double x;
    double y;

    tg_distance_parse_two_no_keywords(argc, argv, &x_value, &y_value);
    x = tg_coerce_finite_double(x_value, "x");
    y = tg_coerce_finite_double(y_value, "y");

    tg_distance_metric_xy(&metric, x, y);
    return rb_float_new(tg_boundary_distance_to_geom(w->geom, &metric));
}

#contains?(other) ⇒ Boolean

Returns:

  • (Boolean)


2043
2044
2045
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2043

static VALUE rb_tg_geometry_geom_contains_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_contains);
}

#covered_by?(other) ⇒ Boolean

Returns:

  • (Boolean)


2063
2064
2065
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2063

static VALUE rb_tg_geometry_geom_covered_by_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_coveredby);
}

#covers?(other) ⇒ Boolean

Returns:

  • (Boolean)


2059
2060
2061
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2059

static VALUE rb_tg_geometry_geom_covers_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_covers);
}

#covers_xy?(x_value, y_value) ⇒ Boolean

Returns:

  • (Boolean)


2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2000

static VALUE rb_tg_geometry_geom_covers_xy_p(VALUE self, VALUE x_value, VALUE y_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    double x = NUM2DBL(x_value);
    double y = NUM2DBL(y_value);
    struct tg_geom *point;
    bool result;

    check_finite_double(x, "x");
    check_finite_double(y, "y");

    {
        struct tg_point tg_point = {x, y};
        point = tg_geom_new_point(tg_point);
    }
    if (!point) {
        rb_raise(rb_eNoMemError, "TG point geometry allocation failed");
    }

    if (tg_geom_error(point)) {
        raise_geom_error_and_free_as(point, eTGGeometryArgumentError,
                                     "TG point geometry allocation failed",
                                     "TG point geometry error message is too large",
                                     "TG point geometry error message allocation failed");
    }

    result = tg_geom_covers(w->geom, point);
    tg_geom_free(point);
    return result ? Qtrue : Qfalse;
}

#dimsObject



2330
2331
2332
2333
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2330

static VALUE rb_tg_geometry_geom_dims(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return INT2NUM(tg_geom_dims(w->geom));
}

#disjoint?(other) ⇒ Boolean

Returns:

  • (Boolean)


2051
2052
2053
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2051

static VALUE rb_tg_geometry_geom_disjoint_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_disjoint);
}

#distance_to_lnglat_meters(*args) ⇒ Object



3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3394

static VALUE rb_tg_geometry_geom_distance_to_lnglat_meters(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE lng_value, lat_value;
    tg_distance_metric_t metric;
    double lng;
    double lat;

    tg_distance_parse_two_no_keywords(argc, argv, &lng_value, &lat_value);
    lng = tg_distance_lng_value(lng_value);
    lat = tg_distance_lat_value(lat_value);

    tg_distance_metric_lnglat(&metric, lng, lat);
    return rb_float_new(tg_distance_to_geom(w->geom, &metric, lng, lat));
}

#distance_to_xy(*args) ⇒ Object



3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3347

static VALUE rb_tg_geometry_geom_distance_to_xy(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE x_value, y_value;
    tg_distance_metric_t metric;
    double x;
    double y;

    tg_distance_parse_two_no_keywords(argc, argv, &x_value, &y_value);
    x = tg_coerce_finite_double(x_value, "x");
    y = tg_coerce_finite_double(y_value, "y");

    tg_distance_metric_xy(&metric, x, y);
    return rb_float_new(tg_distance_to_geom(w->geom, &metric, x, y));
}

#empty?Boolean

Returns:

  • (Boolean)


2325
2326
2327
2328
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2325

static VALUE rb_tg_geometry_geom_empty_p(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return tg_geom_is_empty(w->geom) ? Qtrue : Qfalse;
}

#equals?(other) ⇒ Boolean

Returns:

  • (Boolean)


2039
2040
2041
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2039

static VALUE rb_tg_geometry_geom_equals_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_equals);
}

#extra_coordsObject



2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2361

static VALUE rb_tg_geometry_geom_extra_coords(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int count = tg_geom_num_extra_coords(w->geom);
    const double *coords = tg_geom_extra_coords(w->geom);
    VALUE result = rb_ary_new_capa(count);

    for (int i = 0; i < count; i++) {
        rb_ary_push(result, rb_float_new(coords[i]));
    }

    RB_GC_GUARD(self);
    RB_GC_GUARD(result);
    return result;
}

#extra_jsonObject



2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2270

static VALUE rb_tg_geometry_geom_extra_json(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    const char *extra_json = tg_geom_extra_json(w->geom);
    VALUE str;

    if (!extra_json) {
        return Qnil;
    }

    str = rb_str_new_cstr(extra_json);
    rb_enc_associate(str, rb_utf8_encoding());
    RB_GC_GUARD(str);
    return str;
}

#feature?Boolean

Returns:

  • (Boolean)


2315
2316
2317
2318
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2315

static VALUE rb_tg_geometry_geom_feature_p(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return tg_geom_is_feature(w->geom) ? Qtrue : Qfalse;
}

#feature_collection?Boolean

Returns:

  • (Boolean)


2320
2321
2322
2323
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2320

static VALUE rb_tg_geometry_geom_feature_collection_p(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return tg_geom_is_featurecollection(w->geom) ? Qtrue : Qfalse;
}

#geometriesObject



2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2463

static VALUE rb_tg_geometry_geom_geometries(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int count = tg_geom_num_geometries(w->geom);
    VALUE geometries = rb_ary_new_capa(count);

    for (int i = 0; i < count; i++) {
        rb_ary_push(geometries, geom_wrap_borrowed(self, tg_geom_geometry_at(w->geom, i)));
    }

    RB_GC_GUARD(self);
    RB_GC_GUARD(geometries);
    return geometries;
}

#geometry_at(index_value) ⇒ Object



2456
2457
2458
2459
2460
2461
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2456

static VALUE rb_tg_geometry_geom_geometry_at(VALUE self, VALUE index_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int index = checked_child_index(index_value, tg_geom_num_geometries(w->geom),
                                    "geometry collection child");
    return geom_wrap_borrowed(self, tg_geom_geometry_at(w->geom, index));
}

#has_m?Boolean

Returns:

  • (Boolean)


2340
2341
2342
2343
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2340

static VALUE rb_tg_geometry_geom_has_m_p(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return tg_geom_has_m(w->geom) ? Qtrue : Qfalse;
}

#has_z?Boolean

Returns:

  • (Boolean)


2335
2336
2337
2338
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2335

static VALUE rb_tg_geometry_geom_has_z_p(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return tg_geom_has_z(w->geom) ? Qtrue : Qfalse;
}

#intersects?(other) ⇒ Boolean

Returns:

  • (Boolean)


2047
2048
2049
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2047

static VALUE rb_tg_geometry_geom_intersects_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_intersects);
}

#intersects_rect?(*args) ⇒ Boolean

Returns:

  • (Boolean)


2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2082

static VALUE rb_tg_geometry_geom_intersects_rect_p(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    struct tg_rect rect;

    if (argc == 1) {
        tg_rect_wrapper_t *rect_data = get_rect_wrapper(argv[0]);
        rect.min.x = rect_data->min_x;
        rect.min.y = rect_data->min_y;
        rect.max.x = rect_data->max_x;
        rect.max.y = rect_data->max_y;
    } else if (argc == 4) {
        double min_x = NUM2DBL(argv[0]);
        double min_y = NUM2DBL(argv[1]);
        double max_x = NUM2DBL(argv[2]);
        double max_y = NUM2DBL(argv[3]);

        validate_rect_coordinates(min_x, min_y, max_x, max_y);
        rect.min.x = min_x;
        rect.min.y = min_y;
        rect.max.x = max_x;
        rect.max.y = max_y;
    } else {
        rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1 or 4)", argc);
    }

    return tg_geom_intersects_rect(w->geom, rect) ? Qtrue : Qfalse;
}

#intersects_xy?(x_value, y_value) ⇒ Boolean

Returns:

  • (Boolean)


2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2071

static VALUE rb_tg_geometry_geom_intersects_xy_p(VALUE self, VALUE x_value, VALUE y_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    double x = NUM2DBL(x_value);
    double y = NUM2DBL(y_value);

    check_finite_double(x, "x");
    check_finite_double(y, "y");

    return tg_geom_intersects_xy(w->geom, x, y) ? Qtrue : Qfalse;
}

#lineObject



2295
2296
2297
2298
2299
2300
2301
2302
2303
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2295

static VALUE rb_tg_geometry_geom_line(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);

    if (tg_geom_typeof(w->geom) != TG_LINESTRING) {
        return Qnil;
    }

    return line_wrap_borrowed(self, tg_geom_line(w->geom));
}

#line_at(index_value) ⇒ Object



2406
2407
2408
2409
2410
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2406

static VALUE rb_tg_geometry_geom_line_at(VALUE self, VALUE index_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int index = checked_child_index(index_value, tg_geom_num_lines(w->geom), "geometry line");
    return line_wrap_borrowed(self, tg_geom_line_at(w->geom, index));
}

#linesObject



2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2412

static VALUE rb_tg_geometry_geom_lines(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int count = tg_geom_num_lines(w->geom);
    VALUE lines = rb_ary_new_capa(count);

    for (int i = 0; i < count; i++) {
        rb_ary_push(lines, line_wrap_borrowed(self, tg_geom_line_at(w->geom, i)));
    }

    RB_GC_GUARD(self);
    RB_GC_GUARD(lines);
    return lines;
}

#mObject



2353
2354
2355
2356
2357
2358
2359
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2353

static VALUE rb_tg_geometry_geom_m(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    if (!tg_geom_has_m(w->geom)) {
        return Qnil;
    }
    return rb_float_new(tg_geom_m(w->geom));
}

#nearest_point_lnglat(*args) ⇒ Object



3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3425

static VALUE rb_tg_geometry_geom_nearest_point_lnglat(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE lng_value, lat_value;
    tg_distance_metric_t metric;
    struct tg_point nearest;
    double lng;
    double lat;

    tg_distance_parse_two_no_keywords(argc, argv, &lng_value, &lat_value);
    lng = tg_distance_lng_value(lng_value);
    lat = tg_distance_lat_value(lat_value);

    tg_distance_metric_lnglat(&metric, lng, lat);
    nearest = tg_nearest_point_on_geom(w->geom, &metric);
    return point_array_from_tg_point(nearest);
}

#nearest_point_xy(*args) ⇒ Object



3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
# File 'ext/tg_geometry/tg_geometry_ext.c', line 3377

static VALUE rb_tg_geometry_geom_nearest_point_xy(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE x_value, y_value;
    tg_distance_metric_t metric;
    struct tg_point nearest;
    double x;
    double y;

    tg_distance_parse_two_no_keywords(argc, argv, &x_value, &y_value);
    x = tg_coerce_finite_double(x_value, "x");
    y = tg_coerce_finite_double(y_value, "y");

    tg_distance_metric_xy(&metric, x, y);
    nearest = tg_nearest_point_on_geom(w->geom, &metric);
    return point_array_from_tg_point(nearest);
}

#num_geometriesObject



2451
2452
2453
2454
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2451

static VALUE rb_tg_geometry_geom_num_geometries(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return INT2NUM(tg_geom_num_geometries(w->geom));
}

#num_linesObject



2401
2402
2403
2404
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2401

static VALUE rb_tg_geometry_geom_num_lines(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return INT2NUM(tg_geom_num_lines(w->geom));
}

#num_pointsObject



2376
2377
2378
2379
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2376

static VALUE rb_tg_geometry_geom_num_points(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return INT2NUM(tg_geom_num_points(w->geom));
}

#num_polygonsObject



2426
2427
2428
2429
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2426

static VALUE rb_tg_geometry_geom_num_polygons(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return INT2NUM(tg_geom_num_polys(w->geom));
}

#pointObject



2285
2286
2287
2288
2289
2290
2291
2292
2293
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2285

static VALUE rb_tg_geometry_geom_point(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);

    if (tg_geom_typeof(w->geom) != TG_POINT) {
        return Qnil;
    }

    return point_array_from_tg_point(tg_geom_point(w->geom));
}

#point_at(index_value) ⇒ Object



2381
2382
2383
2384
2385
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2381

static VALUE rb_tg_geometry_geom_point_at(VALUE self, VALUE index_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int index = checked_child_index(index_value, tg_geom_num_points(w->geom), "geometry point");
    return point_array_from_tg_point(tg_geom_point_at(w->geom, index));
}

#pointsObject



2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2387

static VALUE rb_tg_geometry_geom_points(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int count = tg_geom_num_points(w->geom);
    VALUE points = rb_ary_new_capa(count);

    for (int i = 0; i < count; i++) {
        rb_ary_push(points, point_array_from_tg_point(tg_geom_point_at(w->geom, i)));
    }

    RB_GC_GUARD(self);
    RB_GC_GUARD(points);
    return points;
}

#polygonObject



2305
2306
2307
2308
2309
2310
2311
2312
2313
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2305

static VALUE rb_tg_geometry_geom_polygon(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);

    if (tg_geom_typeof(w->geom) != TG_POLYGON) {
        return Qnil;
    }

    return polygon_wrap_borrowed(self, tg_geom_poly(w->geom));
}

#polygon_at(index_value) ⇒ Object



2431
2432
2433
2434
2435
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2431

static VALUE rb_tg_geometry_geom_polygon_at(VALUE self, VALUE index_value) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int index = checked_child_index(index_value, tg_geom_num_polys(w->geom), "geometry polygon");
    return polygon_wrap_borrowed(self, tg_geom_poly_at(w->geom, index));
}

#polygonsObject



2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2437

static VALUE rb_tg_geometry_geom_polygons(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    int count = tg_geom_num_polys(w->geom);
    VALUE polygons = rb_ary_new_capa(count);

    for (int i = 0; i < count; i++) {
        rb_ary_push(polygons, polygon_wrap_borrowed(self, tg_geom_poly_at(w->geom, i)));
    }

    RB_GC_GUARD(self);
    RB_GC_GUARD(polygons);
    return polygons;
}

#sridObject



1967
1968
1969
1970
# File 'ext/tg_geometry/tg_geometry_ext.c', line 1967

static VALUE rb_tg_geometry_geom_srid(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return w->has_srid ? INT2NUM(w->srid) : Qnil;
}

#to_ewkb(*args) ⇒ Object



2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2181

static VALUE rb_tg_geometry_geom_to_ewkb(int argc, VALUE *argv, VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    VALUE kwargs;
    VALUE srid_value;
    VALUE out;
    tg_str_alloc_args_t str_args;
    uint8_t *plain_buf;
    uint8_t *out_buf;
    size_t required;
    size_t written;
    uint8_t byte_order;
    uint32_t type;
    int effective_srid;
    bool explicit_srid;
    int state = 0;

    rb_scan_args(argc, argv, "0:", &kwargs);
    {
        ID allowed[] = {id_srid};
        validate_keywords(kwargs, allowed, sizeof(allowed) / sizeof(allowed[0]));
    }
    explicit_srid = kwargs_has_key(kwargs, id_srid);

    if (explicit_srid) {
        srid_value = rb_hash_aref(kwargs, ID2SYM(id_srid));
        effective_srid = parse_required_srid_value(srid_value);
    } else if (w->has_srid) {
        effective_srid = w->srid;
    } else {
        rb_raise(eTGGeometryArgumentError, "to_ewkb requires srid (geom has no srid metadata)");
    }

    required = tg_geom_wkb(w->geom, NULL, 0);
    if (required < 5) {
        rb_raise(eTGGeometryError, "TG WKB writer produced an invalid header");
    }
    if (required > (size_t)LONG_MAX - 4) {
        rb_raise(rb_eNoMemError, "serialized EWKB output is too large");
    }

    plain_buf = (uint8_t *)ruby_xmalloc(required);
    written = tg_geom_wkb(w->geom, plain_buf, required);
    if (written != required) {
        ruby_xfree(plain_buf);
        rb_raise(eTGGeometryError, "TG WKB writer size changed during serialization");
    }

    byte_order = plain_buf[0];
    if (byte_order > 1) {
        ruby_xfree(plain_buf);
        rb_raise(eTGGeometryError, "TG WKB writer produced invalid byte order");
    }

    type = tg_geometry_read_u32(plain_buf + 1, byte_order);
    if ((type & 0x20000000u) != 0) {
        ruby_xfree(plain_buf);
        rb_raise(eTGGeometryError, "TG WKB writer unexpectedly produced EWKB SRID flag");
    }
    type |= 0x20000000u;

    str_args.len = (long)(required + 4);
    out = rb_protect(tg_str_new_binary_body, (VALUE)&str_args, &state);
    if (state) {
        ruby_xfree(plain_buf);
        rb_jump_tag(state);
    }

    out_buf = (uint8_t *)RSTRING_PTR(out);
    out_buf[0] = byte_order;
    tg_geometry_write_u32(out_buf + 1, type, byte_order);
    tg_geometry_write_u32(out_buf + 5, (uint32_t)effective_srid, byte_order);
    memcpy(out_buf + 9, plain_buf + 5, required - 5);
    ruby_xfree(plain_buf);

    rb_obj_freeze(out);
    RB_GC_GUARD(out);
    return out;
}

#to_geobinObject



2265
2266
2267
2268
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2265

static VALUE rb_tg_geometry_geom_to_geobin(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return binary_writer_result(tg_geom_geobin, w->geom, "GeoBIN");
}

#to_geojsonObject



2133
2134
2135
2136
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2133

static VALUE rb_tg_geometry_geom_to_geojson(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return text_writer_result(tg_geom_geojson, w->geom);
}

#to_hexObject



2260
2261
2262
2263
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2260

static VALUE rb_tg_geometry_geom_to_hex(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return text_writer_result(tg_geom_hex, w->geom);
}

#to_wkbObject



2165
2166
2167
2168
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2165

static VALUE rb_tg_geometry_geom_to_wkb(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return binary_writer_result(tg_geom_wkb, w->geom, "WKB");
}

#to_wktObject



2138
2139
2140
2141
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2138

static VALUE rb_tg_geometry_geom_to_wkt(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    return text_writer_result(tg_geom_wkt, w->geom);
}

#touches?(other) ⇒ Boolean

Returns:

  • (Boolean)


2067
2068
2069
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2067

static VALUE rb_tg_geometry_geom_touches_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_touches);
}

#typeObject



1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
# File 'ext/tg_geometry/tg_geometry_ext.c', line 1972

static VALUE rb_tg_geometry_geom_type(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);

    switch (tg_geom_typeof(w->geom)) {
    case TG_POINT:
        return ID2SYM(rb_intern("point"));
    case TG_LINESTRING:
        return ID2SYM(rb_intern("linestring"));
    case TG_POLYGON:
        return ID2SYM(rb_intern("polygon"));
    case TG_MULTIPOINT:
        return ID2SYM(rb_intern("multipoint"));
    case TG_MULTILINESTRING:
        return ID2SYM(rb_intern("multilinestring"));
    case TG_MULTIPOLYGON:
        return ID2SYM(rb_intern("multipolygon"));
    case TG_GEOMETRYCOLLECTION:
        return ID2SYM(rb_intern("geometrycollection"));
    default:
        return ID2SYM(rb_intern("unknown"));
    }
}

#within?(other) ⇒ Boolean

Returns:

  • (Boolean)


2055
2056
2057
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2055

static VALUE rb_tg_geometry_geom_within_p(VALUE self, VALUE other) {
    return geom_binary_predicate(self, other, tg_geom_within);
}

#zObject



2345
2346
2347
2348
2349
2350
2351
# File 'ext/tg_geometry/tg_geometry_ext.c', line 2345

static VALUE rb_tg_geometry_geom_z(VALUE self) {
    tg_geom_wrapper_t *w = get_geom_wrapper(self);
    if (!tg_geom_has_z(w->geom)) {
        return Qnil;
    }
    return rb_float_new(tg_geom_z(w->geom));
}