diff --git a/eppy/bunch_subclass.py b/eppy/bunch_subclass.py
index ba78e47..f44c648 100644
--- a/eppy/bunch_subclass.py
+++ b/eppy/bunch_subclass.py
@@ -1,5 +1,6 @@
 # Copyright (c) 2012 Santosh Philip
 # Copyright (c) 2016 Jamie Bull
+# Copyright (c) 2020 Cheng Cui
 # =======================================================================
 #  Distributed under the MIT License.
 #  (See accompanying file LICENSE or copy at
diff --git a/eppy/function_helpers.py b/eppy/function_helpers.py
index 140e569..25b8c4d 100644
--- a/eppy/function_helpers.py
+++ b/eppy/function_helpers.py
@@ -1,4 +1,5 @@
 # Copyright (c) 2012 Santosh Philip
+# Copyright (c) 2020 Cheng Cui
 # =======================================================================
 #  Distributed under the MIT License.
 #  (See accompanying file LICENSE or copy at
@@ -58,12 +59,18 @@ def azimuth(ddtt):
 
 
 def true_azimuth(ddtt):
-    """azimuth of the surface"""
+    """true azimuth of the surface"""
     idf = ddtt.theidf
-    building_north_axis = idf.idfobjects["building".upper()][0].North_Axis
-    coords = getcoords(ddtt)
-    surface_azimuth = g_surface.azimuth(coords)
-    return g_surface.true_azimuth(building_north_axis, surface_azimuth)
+    zone_name = ddtt.Zone_Name
+
+    building_north_axis = idf.idfobjects["building"][0].North_Axis
+    zone_direction_of_relative_north = idf.getobject(
+        "zone", zone_name
+    ).Direction_of_Relative_North
+    surface_azimuth = azimuth(ddtt)
+    return g_surface.true_azimuth(
+        building_north_axis, zone_direction_of_relative_north, surface_azimuth
+    )
 
 
 def tilt(ddtt):
diff --git a/eppy/geometry/surface.py b/eppy/geometry/surface.py
index 8d2bfb9..1fb822d 100644
--- a/eppy/geometry/surface.py
+++ b/eppy/geometry/surface.py
@@ -1,4 +1,5 @@
 # Copyright (c) 2012 Tuan Tran
+# Copyright (c) 2020 Cheng Cui
 
 # This file is part of eppy.
 # =======================================================================
@@ -131,10 +132,19 @@ def azimuth(poly):
         return angle2vecs(vec_azi, vec_n)
 
 
-def true_azimuth(building_north_axis, surface_azimuth):
+def true_azimuth(
+    building_north_axis, zone_direction_of_relative_north, surface_azimuth
+):
     """True azimuth of a polygon poly"""
     building_north_axis = 0 if building_north_axis == "" else building_north_axis
-    return (building_north_axis + surface_azimuth) % 360
+    zone_direction_of_relative_north = (
+        0
+        if zone_direction_of_relative_north == ""
+        else zone_direction_of_relative_north
+    )
+    return (
+        building_north_axis + zone_direction_of_relative_north + surface_azimuth
+    ) % 360
 
 
 def tilt(poly):

surface.true_azimuth does not take into account the zone.Direction_of_Relative_North
This issue has been opened to further address the issue of `surface.true_azimuth` discussed in #282 and #283, where `zone.Direction_of_Relative_North` has yet to be included in the calculation.
diff --git a/eppy/tests/geometry_tests/test_surface.py b/eppy/tests/geometry_tests/test_surface.py
index 6d5b32c..a1aeba4 100644
--- a/eppy/tests/geometry_tests/test_surface.py
+++ b/eppy/tests/geometry_tests/test_surface.py
@@ -1,4 +1,5 @@
 # Copyright (c) 2012 Tuan Tran
+# Copyright (c) 2020 Cheng Cui
 # =======================================================================
 #  Distributed under the MIT License.
 #  (See accompanying file LICENSE or copy at
@@ -109,13 +110,21 @@ def test_azimuth():
 def test_true_azimuth():
     """test the true azimuth of a polygon poly"""
     data = (
-        ("", 180, 180),
-        # building_north_axis, surface_azimuth, answer,
-        (20, 0, 20),
-        (240, 180, 60),
+        (45, 30, 0, 75),
+        # building_north_axis, zone_direction_of_relative_north, surface_azimuth, answer,
+        ("", 0, 180, 180),
+        (20, "", 20, 40),
+        (240, 90, 180, 150),
     )
-    for building_north_axis, surface_azimuth, answer in data:
-        result = surface.true_azimuth(building_north_axis, surface_azimuth)
+    for (
+        building_north_axis,
+        zone_direction_of_relative_north,
+        surface_azimuth,
+        answer,
+    ) in data:
+        result = surface.true_azimuth(
+            building_north_axis, zone_direction_of_relative_north, surface_azimuth
+        )
         assert almostequal(answer, result, places=3) == True
 
 
diff --git a/eppy/tests/test_function_helpers.py b/eppy/tests/test_function_helpers.py
index e69de29..3d503c8 100644
--- a/eppy/tests/test_function_helpers.py
+++ b/eppy/tests/test_function_helpers.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2020 Cheng Cui
+# =======================================================================
+#  Distributed under the MIT License.
+#  (See accompanying file LICENSE or copy at
+#  http://opensource.org/licenses/MIT)
+# =======================================================================
+
+"""py.test for function_helpers"""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+from six import StringIO
+
+import eppy.function_helpers as fh
+from eppy.iddcurrent import iddcurrent
+from eppy.modeleditor import IDF
+from eppy.pytest_helpers import almostequal
+
+iddtxt = iddcurrent.iddtxt
+iddfhandle = StringIO(iddcurrent.iddtxt)
+if IDF.getiddname() == None:
+    IDF.setiddname(iddfhandle)
+
+idftxt = """
+    Version,8.0;
+
+    Building,
+        Simple One Zone,         !- Name
+        ;                        !- North Axis {deg} 
+
+    Zone,
+        ZONE ONE,                !- Name
+        ,                        !- Direction of Relative North {deg}
+        0, 0, 0;                            !- X,Y,Z  {m}
+
+    GlobalGeometryRules,
+        UpperLeftCorner,         !- Starting Vertex Position
+        CounterClockWise,        !- Vertex Entry Direction
+        World;                   !- Coordinate System
+
+    BuildingSurface:Detailed,
+        Zn001:Wall001,           !- Name
+        Wall,                    !- Surface Type
+        R13WALL,                 !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Outdoors,                !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        SunExposed,              !- Sun Exposure
+        WindExposed,             !- Wind Exposure
+        0.5000000,               !- View Factor to Ground
+        4,                       !- Number of Vertices
+        0, 0, 4.572000,                     !- X,Y,Z  1 {m}
+        0, 0, 0,                            !- X,Y,Z  2 {m}
+        15.24000, 0, 0,                     !- X,Y,Z  3 {m}
+        15.24000, 0, 4.572000;              !- X,Y,Z  4 {m}
+
+    BuildingSurface:Detailed,
+        Zn001:Wall002,           !- Name
+        Wall,                    !- Surface Type
+        R13WALL,                 !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Outdoors,                !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        SunExposed,              !- Sun Exposure
+        WindExposed,             !- Wind Exposure
+        0.5000000,               !- View Factor to Ground
+        4,                       !- Number of Vertices
+        15.24000, 0, 4.572000,              !- X,Y,Z  1 {m}
+        15.24000, 0, 0,                     !- X,Y,Z  2 {m}
+        15.24000, 15.24000, 0,              !- X,Y,Z  3 {m}
+        15.24000, 15.24000, 4.572000;       !- X,Y,Z  4 {m}
+
+    BuildingSurface:Detailed,
+        Zn001:Wall003,           !- Name
+        Wall,                    !- Surface Type
+        R13WALL,                 !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Outdoors,                !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        SunExposed,              !- Sun Exposure
+        WindExposed,             !- Wind Exposure
+        0.5000000,               !- View Factor to Ground
+        4,                       !- Number of Vertices
+        15.24000, 15.24000, 4.572000,       !- X,Y,Z  1 {m}
+        15.24000, 15.24000, 0,              !- X,Y,Z  2 {m}
+        0, 15.24000, 0,                     !- X,Y,Z  3 {m}
+        0, 15.24000, 4.572000;              !- X,Y,Z  4 {m}
+
+    BuildingSurface:Detailed,
+        Zn001:Wall004,           !- Name
+        Wall,                    !- Surface Type
+        R13WALL,                 !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Outdoors,                !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        SunExposed,              !- Sun Exposure
+        WindExposed,             !- Wind Exposure
+        0.5000000,               !- View Factor to Ground
+        4,                       !- Number of Vertices
+        0, 15.24000, 4.572000,              !- X,Y,Z  1 {m}
+        0, 15.24000, 0,                     !- X,Y,Z  2 {m}
+        0, 0, 0,                            !- X,Y,Z  3 {m}
+        0, 0, 4.572000;                     !- X,Y,Z  4 {m}
+
+    BuildingSurface:Detailed,
+        Zn001:Flr001,            !- Name
+        Floor,                   !- Surface Type
+        FLOOR,                   !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Adiabatic,               !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        NoSun,                   !- Sun Exposure
+        NoWind,                  !- Wind Exposure
+        1.000000,                !- View Factor to Ground
+        4,                       !- Number of Vertices
+        15.24000, 0.000000, 0.0,            !- X,Y,Z  1 {m}
+        0.000000, 0.000000, 0.0,            !- X,Y,Z  2 {m}
+        0.000000, 15.24000, 0.0,            !- X,Y,Z  3 {m}
+        15.24000, 15.24000, 0.0;            !- X,Y,Z  4 {m}
+
+    BuildingSurface:Detailed,
+        Zn001:Roof001,           !- Name
+        Roof,                    !- Surface Type
+        ROOF31,                  !- Construction Name
+        ZONE ONE,                !- Zone Name
+        Outdoors,                !- Outside Boundary Condition
+        ,                        !- Outside Boundary Condition Object
+        SunExposed,              !- Sun Exposure
+        WindExposed,             !- Wind Exposure
+        0,                       !- View Factor to Ground
+        4,                       !- Number of Vertices
+        0.000000, 15.24000, 4.572,          !- X,Y,Z  1 {m}
+        0.000000, 0.000000, 4.572,          !- X,Y,Z  2 {m}
+        15.24000, 0.000000, 4.572,          !- X,Y,Z  3 {m}
+        15.24000, 15.24000, 4.572;          !- X,Y,Z  4 {m}
+"""
+
+
+def test_true_azimuth():
+    """py.test for true_azimuth"""
+    data = (
+        (45, 30, 255),
+        # building_north_axis, zone_direction_of_relative_north, answer,
+        ("", 0, 180),
+        (20, "", 200),
+        (240, 90, 150),
+    )
+
+    fhandle = StringIO(idftxt)
+    idf = IDF(fhandle)
+    building = idf.idfobjects["Building"][0]
+    zone = idf.idfobjects["Zone"][0]
+    surface = idf.idfobjects["BuildingSurface:Detailed"][0]
+
+    for building_north_axis, zone_direction_of_relative_north, answer in data:
+        building.North_Axis = building_north_axis
+        zone.Direction_of_Relative_North = zone_direction_of_relative_north
+        result = fh.true_azimuth(surface)
+        assert almostequal(answer, result, places=3) == True

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
beautifulsoup4==4.8.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
coverage==7.2.7
decorator==5.1.1
-e git+https://github.com/santoshphilip/eppy.git@43068da6e3769f187aecfa7256ad9f94c08b5115#egg=eppy
exceptiongroup==1.2.2
future==1.0.0
importlib-metadata==6.7.0
iniconfig==2.0.0
lxml==5.3.1
munch==4.0.0
packaging==24.0
pluggy==1.2.0
pydot3k==1.0.17
pyparsing==3.1.4
pytest==7.4.4
pytest-cov==4.1.0
six==1.17.0
soupsieve==1.9.6
tinynumpy==1.2.1
tomli==2.0.1
typing_extensions==4.7.1
zipp==3.15.0

name: eppy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - beautifulsoup4==4.8.0
      - coverage==7.2.7
      - decorator==5.1.1
      - exceptiongroup==1.2.2
      - future==1.0.0
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - lxml==5.3.1
      - munch==4.0.0
      - packaging==24.0
      - pluggy==1.2.0
      - pydot3k==1.0.17
      - pyparsing==3.1.4
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - six==1.17.0
      - soupsieve==1.9.6
      - tinynumpy==1.2.1
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - zipp==3.15.0
prefix: /opt/conda/envs/eppy

eppy/tests/geometry_tests/test_surface.py::test_true_azimuth eppy/tests/test_function_helpers.py::test_true_azimuth
eppy/tests/geometry_tests/test_surface.py::test_area eppy/tests/geometry_tests/test_surface.py::test_height eppy/tests/geometry_tests/test_surface.py::test_width eppy/tests/geometry_tests/test_surface.py::test_azimuth eppy/tests/geometry_tests/test_surface.py::test_tilt
eppy/bunch_subclass.py eppy/function_helpers.py eppy/geometry/surface.py
eppy/bunch_subclass.py eppy/function_helpers.py eppy/geometry/surface.py