summaryrefslogtreecommitdiffstats
path: root/src/Cepis/Geo.cs
blob: 75dfa8b9e0502f2d4d5f63fa3111a9648b8a9ac3 (plain)
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
using System.Text.Json.Serialization;

namespace Cepis;

/// <summary>
/// The CEP's coordinate, when the database has one.
/// </summary>
/// <remarks>
/// <para>
/// The point is the <b>median</b> of the coordinates of that CEP's addresses,
/// not the mean: one badly geocoded address 40 km away shifts a mean and does
/// not move a median.
/// </para>
/// <para>
/// Always check <see cref="Precisao"/> before using <see cref="Lat"/> and
/// <see cref="Lon"/> for distance. <c>"logradouro"</c> means the point is a
/// stretch of street and <see cref="RaioM"/> lands around 100–150 m — good for
/// maps and for distance. <c>"localidade"</c> means the CEP <i>is</i> the whole
/// municipality (a city-wide general CEP) and the point is its centroid, with
/// <see cref="RaioM"/> running from 7 km to 40 km; computing shipping from that
/// is wrong by tens of kilometres.
/// </para>
/// <para>
/// <see cref="RaioM"/> is the radius containing 90% of that CEP's addresses. It
/// exists precisely so that error cannot pass unnoticed.
/// </para>
/// <para>
/// The property names are the API's own, with only the casing adapted:
/// <c>lat</c>, <c>lon</c>, <c>raio_m</c> and <c>precisao</c> on the wire.
/// </para>
/// </remarks>
public sealed record Geo
{
    /// <summary>Latitude in decimal degrees, WGS 84. Wire name <c>lat</c>.</summary>
    [JsonPropertyName("lat")]
    public double Lat { get; init; }

    /// <summary>Longitude in decimal degrees, WGS 84. Wire name <c>lon</c>.</summary>
    [JsonPropertyName("lon")]
    public double Lon { get; init; }

    /// <summary>
    /// The radius, in metres, containing 90% of that CEP's addresses. Wire name
    /// <c>raio_m</c>.
    /// </summary>
    [JsonPropertyName("raio_m")]
    public int RaioM { get; init; }

    /// <summary>
    /// What the point describes: <c>"logradouro"</c> for a stretch of street,
    /// <c>"localidade"</c> for a municipality centroid. Wire name
    /// <c>precisao</c>.
    /// </summary>
    [JsonPropertyName("precisao")]
    public string Precisao { get; init; } = "";

    /// <summary>
    /// <see langword="true"/> when the coordinate points at a street rather than
    /// a municipality.
    /// </summary>
    /// <remarks>
    /// Shorthand for <c>Precisao == "logradouro"</c>, which is the check to make
    /// before using the point to measure distance.
    /// </remarks>
    [JsonIgnore]
    public bool IsPrecise => Precisao == "logradouro";
}