1
\$\begingroup\$

I am creating an Ellipsoid class and I then want to instantiate a few constants (pre-defined Ellipsoids).
Below is my current implementation. I am not really satisfied with it except that it works very well but feels a but clumsy and there is probably a much cleaner way to do this.

# -*- coding: utf-8 -*-

from collections import namedtuple

ELLIPSOID_DEFS = (
    (6377563.396, 299.3249646, 'airy', 'Airy 1830', 'Britain', 7001),
    (6377340.189, 299.3249646, 'mod_airy', 'Airy Modified 1849', 'Ireland', 7002),
    (6378160, 298.25, 'aust_SA', 'Australian National Spheroid', 'Australia', 7003),
    (6377397.155, 299.1528128, 'bessel', 'Bessel 1841', 'Europe, Japan', 7004),
    (6377492.018, 299.1528128, 'bessel_mod', 'Bessel Modified', 'Norway, Sweden w/ 1mm increase of semi-major axis', 7005),
    (6378206.4, 294.9786982, 'clrk_66', 'Clarke 1866', 'North America', 7008),
    (6378249.145, 293.465, 'clarke_rgs', 'Clarke 1880 (RGS)', 'France, Africa', 7012),
    (6378249.145, 293.4663077, 'clarke_arc', 'Clarke 1880 (Arc)', 'South Africa', 7013),
    (6377276.345, 300.8017, 'evrst30', 'Everest 1830 (1937 Adjustment)', 'India', 7015),
    (6377298.556, 300.8017, 'evrstSS', 'Everest 1830 (1967 Definition)', 'Brunei & East Malaysia', 7016),
    (6377304.063, 300.8017, 'evrst48', 'Everest 1830 Modified', 'West Malaysia & Singapore', 7018),
    (6378137, 298.257222101, 'grs80', 'GRS 1980', 'Global ITRS', 7019),
    (6378200, 298.3, 'helmert', 'Helmert 1906', 'Egypt', 7020),
    (6378388, 297, 'intl', 'International 1924', 'Europe', 7022),
    (6378245, 298.3, 'krass', 'Krassowsky 1940', 'USSR, Russia, Romania', 7024),
    (6378145, 298.25, 'nwl9d', 'NWL 9D', 'USA/DoD', 7025),
    (6376523, 308.64, 'plessis', 'Plessis 1817', 'France', 7027),
    (6378137, 298.257223563, 'wgs84', 'WGS 84', 'Global GPS', 7030),
    (6378160, 298.247167427, 'grs67', 'GRS 1967', '', 7036),
    (6378135, 298.26, 'wgs72', 'WGS 72', 'USA/DoD', 7043),
    (6377301.243, 300.8017255, 'everest_1962', 'Everest 1830 (1962 Definition)', 'Pakistan', 7044),
    (6377299.151, 300.8017255, 'everest_1975', 'Everest 1830 (1975 Definition)', 'India', 7045),
    (6377483.865, 299.1528128, 'bess_nam', 'Bessel Namibia (GLM)', 'Namibia', 7046),
    (6377295.664, 300.8017, 'evrst69', 'Everest 1830 (RSO 1969)', 'Malaysia', 7056)
)

"""
Ellipsdoids = definitions: as per above 'a rf alias name area epsg'
"""
Ellipsoid_Definition = namedtuple('Ellipsoid_Definition', 'a rf alias name area epsg')

class Ellipsoid():
    def __init__(self, a, rf, alias='user', name='User Defined', area='local', epsg=None):
        self.a = a
        self.rf = rf
        self.alias = alias
        self.name = name
        self.area = area
        self.epsg = epsg

    def __repr__(self):
        return f'<Ellipsoid(name="{self.name}", epsg={self.epsg}, a={self.a}, rf={self.rf})>'

    @property
    def b(self):
        # semi-minor axis
        return self.a * (1 - 1 / self.rf)

    @property
    def e2(self):
        # squared eccentricity
        rf = self.rf
        return (2 - 1 / rf) / rf

    @property
    def n(self):
        # third flattening
        a = self.a
        b = self.b
        return (a - b) / (a + b)

    @classmethod
    def from_def(cls, ellps_def):
        if isinstance(ellps_def, Ellipsoid_Definition):
            return cls(ellps_def.a, ellps_def.rf, alias=ellps_def.alias, name=ellps_def.name, area=ellps_def.area, epsg=ellps_def.epsg)
        else:
            raise ValueError('invalid ellipsoid definition')


class Ellipsoids():
    def __init__(self, ellps_defs=ELLIPSOID_DEFS):
        for ellps_def in ellps_defs:
            ellps = Ellipsoid_Definition(*ellps_def)
            self.__dict__[ellps.alias] = Ellipsoid(*ellps)


ELLIPSOIDS = Ellipsoids()
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I would explicitly refer the constants in class variables :

class Elipsoids:
    airy = Elipsoid(6377563.396, 299.3249646, 'airy', 'Airy 1830', 'Britain', 7001),
    mod_airy = Elipsoid(6377340.189, 299.3249646, 'mod_airy', 'Airy Modified 1849', 'Ireland', 7002),
    ...

This way :

  • You get rid of global variables : you simply do module.Elipsoids.airy .
  • You get rid of dirty assigning code
  • You can get rid of alias if it's not used anywhere else in the code
  • You get more readable access to variables
\$\endgroup\$
1
  • \$\begingroup\$ Yup, much cleaner indeed. I was too biased trying to keep the definitions in a variable. Thanks! \$\endgroup\$
    – YeO
    Commented Nov 15, 2018 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.