Add graphics with renderer

View on GitHubSample viewer app

A renderer allows you to change the style of all graphics in a graphics overlay by referencing a single symbol style. A renderer will only affect graphics that do not specify their own symbol style.

Image of add graphics with renderer

Use case

A renderer allows you to change the style of all graphics in an overlay by only changing one copy of the symbol. For example, a user may wish to display a number of graphics on a map of parkland which represent trees, all sharing a common symbol.

How to use the sample

Pan and zoom on the map to view graphics for points, lines, and polygons (including polygons with curve segments), which are stylized using renderers.

How it works

  1. Create an AGSGraphicsOverlay and add it to the AGSMapView.
  2. Create an AGSGraphic, specifying only an AGSGeometry.
  3. Create a single AGSSymbol such as an AGSSimpleMarkerSymbol.
  4. Create a renderer with AGSSimpleRenderer(symbol:), passing in an AGSSymbol.
  5. Set the renderer for the AGSGraphicsOverlay.

Relevant API

  • AGSCubicBezierSegment
  • AGSEllipticArcSegment
  • AGSGeodesicEllipseParameters
  • AGSGeometry
  • AGSGraphic
  • AGSGraphicsOverlay
  • AGSMutablePart
  • AGSPolygonBuilder
  • AGSPolylineBuilder
  • AGSSimpleFillSymbol
  • AGSSimpleLineSymbol
  • AGSSimpleMarkerSymbol
  • AGSSimpleRenderer
  • class AGSGeometryEngine.geodesicEllipse(with:)

Additional information

To set unique symbols across a number of graphics (e.g. showing graphics of individual landmarks), see "Add graphics with symbols" sample.

Tags

arc, bezier, curve, display, ellipse, graphics, marker, overlay, renderer, segment, symbol, true curve

Sample Code

AddGraphicsWithRendererViewController.swift
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright 2016 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import UIKit
import ArcGIS

class AddGraphicsWithRendererViewController: UIViewController {
    // MARK: Storyboard views

    /// The map view managed by the view controller.
    @IBOutlet var mapView: AGSMapView! {
        didSet {
            mapView.map = AGSMap(basemapStyle: .arcGISTopographic)
            mapView.setViewpointCenter(AGSPointMakeWebMercator(20e5, 20e5), scale: 7e7)
            mapView.graphicsOverlays.addObjects(from: [
                makePointGraphicsOverlay(),
                makeLineGraphicsOverlay(),
                makeSquarePolygonGraphicsOverlay(),
                makeEllipseGraphicsOverlay(),
                makeCurvedPolygonGraphicsOverlay()
            ])
        }
    }

    // MARK: Methods

    func makePointGraphicsOverlay() -> AGSGraphicsOverlay {
        // Create a simple marker symbol.
        let pointSymbol = AGSSimpleMarkerSymbol(style: .diamond, color: .green, size: 10)
        // Create a graphics overlay for the points.
        let pointGraphicsOverlay = AGSGraphicsOverlay()
        // Create and assign a simple renderer to the graphics overlay.
        pointGraphicsOverlay.renderer = AGSSimpleRenderer(symbol: pointSymbol)

        // Create a point graphic with `AGSPoint` geometry.
        let pointGeometry = AGSPoint(x: 40e5, y: 40e5, spatialReference: .webMercator())
        let pointGraphic = AGSGraphic(geometry: pointGeometry, symbol: nil)
        // Add the graphic to the overlay.
        pointGraphicsOverlay.graphics.add(pointGraphic)
        return pointGraphicsOverlay
    }

    func makeLineGraphicsOverlay() -> AGSGraphicsOverlay {
        // Create a simple line symbol.
        let lineSymbol = AGSSimpleLineSymbol(style: .solid, color: .blue, width: 5)
        // Create a graphics overlay for the polylines.
        let lineGraphicsOverlay = AGSGraphicsOverlay()
        // Create and assign a simple renderer to the graphics overlay.
        lineGraphicsOverlay.renderer = AGSSimpleRenderer(symbol: lineSymbol)

        // Create a line graphic with `AGSPolyline` geometry.
        let lineBuilder = AGSPolylineBuilder(spatialReference: .webMercator())
        lineBuilder.addPointWith(x: -10e5, y: 40e5)
        lineBuilder.addPointWith(x: 20e5, y: 50e5)
        let lineGraphic = AGSGraphic(geometry: lineBuilder.toGeometry(), symbol: nil)
        // Add the graphic to the overlay.
        lineGraphicsOverlay.graphics.add(lineGraphic)
        return lineGraphicsOverlay
    }

    func makeSquarePolygonGraphicsOverlay() -> AGSGraphicsOverlay {
        // Create a simple fill symbol.
        let squareSymbol = AGSSimpleFillSymbol(style: .solid, color: .yellow, outline: nil)
        // Create a graphics overlay for the square polygons.
        let squareGraphicsOverlay = AGSGraphicsOverlay()
        // Create and assign a simple renderer to the graphics overlay.
        squareGraphicsOverlay.renderer = AGSSimpleRenderer(symbol: squareSymbol)

        // Create a polygon graphic with `AGSPolygon` geometry.
        let polygonBuilder = AGSPolygonBuilder(spatialReference: .webMercator())
        polygonBuilder.addPointWith(x: -20e5, y: 20e5)
        polygonBuilder.addPointWith(x: 20e5, y: 20e5)
        polygonBuilder.addPointWith(x: 20e5, y: -20e5)
        polygonBuilder.addPointWith(x: -20e5, y: -20e5)
        let polygonGraphic = AGSGraphic(geometry: polygonBuilder.toGeometry(), symbol: nil)
        // Add the graphic to the overlay.
        squareGraphicsOverlay.graphics.add(polygonGraphic)
        return squareGraphicsOverlay
    }

    func makeEllipseGraphicsOverlay() -> AGSGraphicsOverlay {
        // Create a simple fill symbol.
        let ellipseSymbol = AGSSimpleFillSymbol(style: .solid, color: .purple, outline: nil)
        // Create a graphics overlay for the ellipse.
        let ellipseGraphicsOverlay = AGSGraphicsOverlay()
        // Create and assign a simple renderer to the graphics overlay.
        ellipseGraphicsOverlay.renderer = AGSSimpleRenderer(symbol: ellipseSymbol)

        // Create an ellipse graphic.
        let ellipseCenter = AGSPoint(x: 40e5, y: 25e5, spatialReference: .webMercator())
        let parameters = AGSGeodesicEllipseParameters(
            axisDirection: -45,
            angularUnit: .degrees(),
            center: ellipseCenter,
            linearUnit: .kilometers(),
            maxPointCount: 100,
            maxSegmentLength: 20,
            geometryType: .polygon,
            semiAxis1Length: 200,
            semiAxis2Length: 400
        )
        let ellipseGeometry = AGSGeometryEngine.geodesicEllipse(with: parameters)
        let ellipseGraphic = AGSGraphic(geometry: ellipseGeometry, symbol: nil)

        // Add the graphic to the overlay.
        ellipseGraphicsOverlay.graphics.add(ellipseGraphic)
        return ellipseGraphicsOverlay
    }

    func makeCurvedPolygonGraphicsOverlay() -> AGSGraphicsOverlay {
        // Create a simple fill symbol with outline.
        let curvedLineSymbol = AGSSimpleLineSymbol(style: .solid, color: .black, width: 1)
        let curvedFillSymbol = AGSSimpleFillSymbol(style: .solid, color: .red, outline: curvedLineSymbol)
        // Create a graphics overlay for the polygons with curve segments.
        let curvedGraphicsOverlay = AGSGraphicsOverlay()
        // Create and assign a simple renderer to the graphics overlay.
        curvedGraphicsOverlay.renderer = AGSSimpleRenderer(symbol: curvedFillSymbol)

        // Create a heart-shape graphic from `AGSSegment`s.
        let origin = AGSPoint(x: 40e5, y: 5e5, spatialReference: .webMercator())
        let heartGeometry = makeHeartGeometry(center: origin, sideLength: 10e5)
        let heartGraphic = AGSGraphic(geometry: heartGeometry, symbol: nil)
        curvedGraphicsOverlay.graphics.add(heartGraphic)
        return curvedGraphicsOverlay
    }

    /// Create a heart-shape geometry with Bezier and elliptic arc segments.
    ///
    /// - Parameters:
    ///   - center: The center of the square that contains the heart shape.
    ///   - sideLength: The side length of the square.
    /// - Returns: A heart-shape geometry.
    func makeHeartGeometry(center: AGSPoint, sideLength: Double) -> AGSGeometry? {
        guard sideLength > 0 else { return nil }
        let spatialReference = center.spatialReference
        // The x and y coordinates to simplify the calculation.
        let minX = center.x - 0.5 * sideLength
        let minY = center.y - 0.5 * sideLength
        // The radius of the arcs.
        let arcRadius = sideLength * 0.25

        // Bottom left curve.
        let leftCurveStart = AGSPoint(x: center.x, y: minY, spatialReference: spatialReference)
        let leftCurveEnd = AGSPoint(x: minX, y: minY + 0.75 * sideLength, spatialReference: spatialReference)
        let leftControlPoint1 = AGSPoint(x: center.x, y: minY + 0.25 * sideLength, spatialReference: spatialReference)
        let leftControlPoint2 = AGSPoint(x: minX, y: center.y, spatialReference: spatialReference)
        let leftCurve = AGSCubicBezierSegment(start: leftCurveStart, controlPoint1: leftControlPoint1, controlPoint2: leftControlPoint2, end: leftCurveEnd, spatialReference: spatialReference)!

        // Top left arc.
        let leftArcCenter = AGSPoint(x: minX + 0.25 * sideLength, y: minY + 0.75 * sideLength, spatialReference: spatialReference)
        let leftArc = AGSEllipticArcSegment.createCircularEllipticArc(withCenter: leftArcCenter, radius: arcRadius, startAngle: .pi, centralAngle: -.pi, spatialReference: spatialReference)!

        // Top right arc.
        let rightArcCenter = AGSPoint(x: minX + 0.75 * sideLength, y: minY + 0.75 * sideLength, spatialReference: spatialReference)
        let rightArc = AGSEllipticArcSegment.createCircularEllipticArc(withCenter: rightArcCenter, radius: arcRadius, startAngle: .pi, centralAngle: -.pi, spatialReference: spatialReference)!

        // Bottom right curve.
        let rightCurveStart = AGSPoint(x: minX + sideLength, y: minY + 0.75 * sideLength, spatialReference: spatialReference)
        let rightCurveEnd = leftCurveStart
        let rightControlPoint1 = AGSPoint(x: minX + sideLength, y: center.y, spatialReference: spatialReference)
        let rightControlPoint2 = leftControlPoint1
        let rightCurve = AGSCubicBezierSegment(start: rightCurveStart, controlPoint1: rightControlPoint1, controlPoint2: rightControlPoint2, end: rightCurveEnd, spatialReference: spatialReference)!

        let heart = AGSMutablePart(spatialReference: spatialReference)
        [leftCurve, leftArc, rightArc, rightCurve].forEach { heart.add($0) }
        let heartShape = AGSPolygonBuilder(spatialReference: spatialReference)
        heartShape.parts.add(heart)
        return heartShape.toGeometry()
    }

    // MARK: UIViewController

    override func viewDidLoad() {
        super.viewDidLoad()
        // Add the source code button item to the right of navigation bar.
        (navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["AddGraphicsWithRendererViewController"]
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.