| 537 | | |
|---|
| | 537 | The coordinate sequences of these sub-geometries can then be accessed as |
|---|
| | 538 | described above. |
|---|
| | 539 | |
|---|
| | 540 | Interoperation |
|---|
| | 541 | ============== |
|---|
| | 542 | |
|---|
| | 543 | Shapely provides 4 avenues for interoperation with other Python and GIS |
|---|
| | 544 | software. |
|---|
| | 545 | |
|---|
| | 546 | Well-known Formats |
|---|
| | 547 | ------------------ |
|---|
| | 548 | |
|---|
| | 549 | Well-known Text (WKT) |
|---|
| | 550 | +++++++++++++++++++++ |
|---|
| | 551 | |
|---|
| | 552 | The WKT representation of any geometry object can be had via the **wkt** |
|---|
| | 553 | attribute: |
|---|
| | 554 | |
|---|
| | 555 | .. code-block:: python |
|---|
| | 556 | |
|---|
| | 557 | >>> point_r.wkt |
|---|
| | 558 | 'POINT (-1.5000000000000000 1.2000000000000000)' |
|---|
| | 559 | |
|---|
| | 560 | Hex-encode that string and you have a value that can be conveniently inserted directly into PostGIS |
|---|
| | 561 | |
|---|
| | 562 | .. code-block:: python |
|---|
| | 563 | |
|---|
| | 564 | >>> point_r.wkt.encode('hex') |
|---|
| | 565 | '504f494e5420282d312e3530303030303030303030303030303020312e3230303030303030303030303030303029' |
|---|
| | 566 | |
|---|
| | 567 | New geometries can be created from WKT representations using the |
|---|
| | 568 | *shapely.wkt.loads* factory (inspired by the *pickle* module) |
|---|
| | 569 | |
|---|
| | 570 | .. code-block:: python |
|---|
| | 571 | |
|---|
| | 572 | >>> from shapely.wkt import loads |
|---|
| | 573 | >>> loads('POINT (0 0)') |
|---|
| | 574 | <shapely.geometry.point.Point object at ...> |
|---|
| | 575 | |
|---|
| | 576 | Well-known Binary (WKB) |
|---|
| | 577 | +++++++++++++++++++++++ |
|---|
| | 578 | |
|---|
| | 579 | The WKB representation of any geometry object can be had via the **wkb** |
|---|
| | 580 | attribute. New geometries can be created from WKB data using the |
|---|
| | 581 | *shapely.wkb.loads* factory. Use this format to interoperate with ogr.py: |
|---|
| | 582 | |
|---|
| | 583 | .. code-block:: python |
|---|
| | 584 | |
|---|
| | 585 | >>> import ogr |
|---|
| | 586 | >>> from shapely.wkb import loads |
|---|
| | 587 | >>> source = ogr.Open("/tmp/world_borders.shp") |
|---|
| | 588 | >>> borders = source.GetLayerByName("world_borders") |
|---|
| | 589 | >>> feature = borders.GetNextFeature() |
|---|
| | 590 | >>> loads(feature.GetGeometryRef().ExportToWkb()) |
|---|
| | 591 | <shapely.geometry.polygon.Polygon object at ...> |
|---|
| | 592 | |
|---|
| | 593 | Python Sequences |
|---|
| | 594 | ---------------- |
|---|
| | 595 | |
|---|
| | 596 | Python sequence data can be analyzed as Shapely geometries using the |
|---|
| | 597 | *shapely.geometry.as\** adapters while leaving the data in its original |
|---|
| | 598 | storage. A pair of float can be treated as a point with **asPoint**: |
|---|
| | 599 | |
|---|
| | 600 | .. code-block:: python |
|---|
| | 601 | |
|---|
| | 602 | >>> from shapely.geometry import asPoint |
|---|
| | 603 | >>> coords = [3.0, 4.0] |
|---|
| | 604 | >>> pa = asPoint(coords) |
|---|
| | 605 | >>> pa.wkt |
|---|
| | 606 | 'POINT (3.0000000000000000 4.0000000000000000)' |
|---|
| | 607 | |
|---|
| | 608 | Move the coordinates and watch the geometry adapter change |
|---|
| | 609 | |
|---|
| | 610 | .. code-block:: python |
|---|
| | 611 | |
|---|
| | 612 | >>> coords[0] = 1.0 |
|---|
| | 613 | >>> pa.wkt |
|---|
| | 614 | 'POINT (1.0000000000000000 4.0000000000000000)' |
|---|
| | 615 | |
|---|
| | 616 | The **asLineString** adapter works much the same. The **asPolygon** adapter is |
|---|
| | 617 | used like |
|---|
| | 618 | |
|---|
| | 619 | .. code-block:: python |
|---|
| | 620 | |
|---|
| | 621 | >>> from shapely.geometry import asPolygon |
|---|
| | 622 | >>> coords = [[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]] |
|---|
| | 623 | >>> hole_coords = [((0.1,0.1), (0.1,0.2), (0.2,0.2), (0.2,0.1))] |
|---|
| | 624 | >>> pa = asPolygon(coords, hole_coords) |
|---|
| | 625 | >>> len(pa.exterior.coords) |
|---|
| | 626 | 5 |
|---|
| | 627 | >>> len(pa.interiors) |
|---|
| | 628 | 1 |
|---|
| | 629 | >>> len(pa.interiors[0].coords) |
|---|
| | 630 | 5 |
|---|
| | 631 | |
|---|
| | 632 | Numpy Array Interface |
|---|
| | 633 | --------------------- |
|---|
| | 634 | |
|---|
| | 635 | Shapely geometries provide the Numpy array interface which means that points, |
|---|
| | 636 | line strings, and polygon rings can be used as Numpy arrays: |
|---|
| | 637 | |
|---|
| | 638 | .. code-block:: python |
|---|
| | 639 | |
|---|
| | 640 | >>> from numpy import array |
|---|
| | 641 | >>> a = array(polygon.exterior) |
|---|
| | 642 | >>> a |
|---|
| | 643 | array([[-1., -1.], |
|---|
| | 644 | [-1., 1.], |
|---|
| | 645 | [ 1., 1.], |
|---|
| | 646 | [ 1., -1.], |
|---|
| | 647 | [-1., -1.]]) |
|---|
| | 648 | |
|---|
| | 649 | The *numpy.asarray* function does not copy coordinate values at the price of |
|---|
| | 650 | slower numpy access to coordinates. |
|---|
| | 651 | |
|---|
| | 652 | The *shapely.geometry.as\** functions can also be used to wrap numpy arrays, |
|---|
| | 653 | which can then be analyzed using Shapely while maintaining their original |
|---|
| | 654 | storage. A 1 x 2 array can be adapted to a point |
|---|
| | 655 | |
|---|
| | 656 | .. code-block:: python |
|---|
| | 657 | |
|---|
| | 658 | >>> a = array([1.0, 2.0]) |
|---|
| | 659 | >>> pa = asPoint(a) |
|---|
| | 660 | >>> pa.wkt |
|---|
| | 661 | 'POINT (1.0000000000000000 2.0000000000000000)' |
|---|
| | 662 | |
|---|
| | 663 | and a N x 2 array can be adapted to a line string |
|---|
| | 664 | |
|---|
| | 665 | .. code-block:: python |
|---|
| | 666 | |
|---|
| | 667 | >>> from shapely.geometry import asLineString |
|---|
| | 668 | >>> a = array([[1.0, 2.0], [3.0, 4.0]]) |
|---|
| | 669 | >>> la = asLineString(a) |
|---|
| | 670 | >>> la.wkt |
|---|
| | 671 | 'LINESTRING (1.0000000000000000 2.0000000000000000, 3.0000000000000000 4.0000000000000000)' |
|---|
| | 672 | |
|---|
| | 673 | There is no Numpy array representation of a polygon. |
|---|
| | 674 | |
|---|
| | 675 | Python Geo Interface |
|---|
| | 676 | -------------------- |
|---|
| | 677 | |
|---|
| | 678 | Any object that provides the GeoJSON-like `Python geo interface`_ can be |
|---|
| | 679 | treated as a Shapely geometry using the *shapely.geometry.asShape* function. |
|---|
| | 680 | For example, a dictionary: |
|---|
| | 681 | |
|---|
| | 682 | .. code-block:: python |
|---|
| | 683 | |
|---|
| | 684 | >>> from shapely.geometry import asShape |
|---|
| | 685 | >>> d = {"type": "Point", "coordinates": (0.0, 0.0)} |
|---|
| | 686 | >>> shape = asShape(d) |
|---|
| | 687 | >>> shape.geom_type |
|---|
| | 688 | 'Point' |
|---|
| | 689 | >>> list(shape.coords) |
|---|
| | 690 | [(0.0, 0.0)] |
|---|
| | 691 | |
|---|
| | 692 | Or a simple placemark-type object: |
|---|
| | 693 | |
|---|
| | 694 | .. code-block:: python |
|---|
| | 695 | |
|---|
| | 696 | >>> class GeoThing(object): |
|---|
| | 697 | ... def __init__(self, d): |
|---|
| | 698 | ... self.__geo_interface__ = d |
|---|
| | 699 | >>> thing = GeoThing({"type": "Point", "coordinates": (0.0, 0.0)}) |
|---|
| | 700 | >>> shape = asShape(thing) |
|---|
| | 701 | >>> shape.geom_type |
|---|
| | 702 | 'Point' |
|---|
| | 703 | >>> list(shape.coords) |
|---|
| | 704 | [(0.0, 0.0)] |
|---|
| | 705 | |
|---|
| | 706 | .. _Python geo interface: http://trac.gispython.org/projects/PCL/wiki/PythonGeoInterface |
|---|
| | 707 | |
|---|