sxtwl_cpp

repository·master·Indexed 42 days ago

https://github.com/yuangu/sxtwl_cpp

A high-performance C++ library implementing the Shou Xing Astronomical Calendar. It provides accurate solar and lunar calendar data for dates after 722 BC, suitable for maritime, astronomical, and archaeological applications. The library supports multiple platforms (Android, iOS, Windows, macOS, Linux) and provides language bindings for Python, Lua, Java, C#, PHP, and Go via SWIG.

Tokens
6.2K
Snippets
32
Records
34
Agent score
47%

What's inside sxtwl_cpp

  1. Overview of sxtwl_cpp

    master

    sxtwl_cpp is a C++ implementation of the Shou Xing Astronomical Calendar (寿星天文历). It uses astronomical algorithms to provide a wide query range, accurate for dates after 722 BC.

    Key features include:

    • Multi-platform support: Android, iOS, Windows, macOS, and Linux.
    • Language bindings: Interfaces are exposed to Python, Lua, Java, C#, and PHP via SWIG.
    • High performance: The v2.x redesign significantly improved performance over previous versions.
    • No external data required: The library does not require accompanying table data files.

    Common use cases include maritime navigation (lunar calendar/nongli), astrology/metaphysics research, archaeology, and astronomical studies.

  2. Install sxtwl via pip

    master

    To install the sxtwl library for Python, use the standard pip command.

    If you need to maintain compatibility with older projects using version 1.x, you can specify version 1.1.0.

    # Install latest version
    pip install sxtwl
    
    # Install for compatibility with V1.x projects
    pip install sxtwl==1.1.0
  3. Build sxtwl_cpp using CMake command line

    master

    You can build the project using the command line interface. To build the core library and its examples, follow these steps:

    1. Create and enter a build directory.
    2. Run cmake with the SXTWL_BUILD_EXAMPLES flag if you want to compile examples.
    3. Execute the build command.

    To specify a different generator (e.g., Unix Makefiles), use the -G flag. You can list available generators by running cmake --help or cmake .. -G.

    $ mkdir build
    $ cd build
    $ cmake .. -DSXTWL_BUILD_EXAMPLES=1  
    $ cmake --build .
  4. Install and build sxtwl_cpp using CMake GUI

    master

    For users preferring a graphical interface on Windows, use cmake-gui to build the project:

    1. Set Paths: In cmake-gui, set "where is the source code" to your project directory and "where to build the binaries" to a build directory (e.g., a build subdirectory within the project).
    2. Generate: Click Generate. Select your preferred IDE (e.g., Visual Studio 2015) and click Finish.
    3. Configure: Click Configure.
    4. Build: Click Open Project to open the project in your IDE and compile the library.

    To build examples: Click Add Entry, set the Name to SXTWL_BUILD_EXAMPLES, check the Value box, click OK, and then click Configure again.

    1. Where is the source code: [path/to/sxtwl_cpp]
    2. Where to build the binaries: [path/to/sxtwl_cpp/build]
    3. Click 'Generate' -> Select IDE
    4. Click 'Configure' -> Click 'Open Project'
  5. Build sxtwl_cpp for Android

    master

    Integration into an Android Project

    1. Copy or clone the sxtwl_cpp source code into your Android project directory.
    2. Refresh Gradle (it is recommended to manually delete the .externalNativeBuild directory first).
    3. In your Java code, load the library using:
      System.loadLibrary("sxtwl_java");
      Note: If using Android's externalNativeBuild, add "-DSXTWL_WRAPPER_JAVA=1" to the CMake arguments.

    Independent Android Compilation (Standalone)

    To compile for Android independently using the NDK, set the following environment variables and run the CMake command:

    Supported ABIs (ANDROID_ABI): armeabi, armeabi-v7a, x86, mips, armeabi-v7a with NEON, armeabi-v7a with VFPV3, armeabi-v6 with VFP, arm64-v8a, x86_64, mips64.

    Troubleshooting SWIG: If you encounter Could NOT SWIG (missing: SWIG_DIR), specify the SWIG path using -DSWIG_EXECUTABLE=[path/to/swig].

    # Standalone Android Build Example
    $ set ANDROID_SDK=D:/android/sdk
    $ set ANDROID_NDK=D:/android/android-ndk-r14b
    $ set ANDROID_ABI=armeabi
    $ set ANDROID_CMAKE=%ANDROID_SDK%/cmake/3.6.4111459/bin/cmake.exe
    $ set ANDROID_NINJA=%ANDROID_SDK%/cmake/3.6.4111459/bin/ninja.exe
    
    $ %ANDROID_CMAKE% -DANDROID_ABI=%ANDROID_ABI%   \ 
    -DANDROID_PLATFORM=android-16  \ 
    -DCMAKE_BUILD_TYPE=Release   \ 
    -DANDROID_NDK=%ANDROID_NDK%    \ 
    -DCMAKE_CXX_FLAGS=-std=c++11 -frtti -fexceptions   \ 
    -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%/build/cmake/android.toolchain.cmake    \ 
    -DCMAKE_MAKE_PROGRAM=%ANDROID_NINJA% -G "Ninja"    \ 
    -DCONSOLE=1   \ 
    -DSXTWL_WRAPPER_JAVA=1 ..  
    
    $ %ANDROID_CMAKE% --build .
  6. Query Solar Terms (Jie Qi)

    master

    You can check if a specific day is a Solar Term and retrieve its details:

    1. Check if the day has a Solar Term: hasJieQi().
    2. Get the index of the Solar Term: getJieQi().
    3. Get the Julian Day (JD) of the Solar Term: getJieQiJD().
    4. Convert Julian Day to a date object: sxtwl.JD2DD(jd).

    To find the next or previous Solar Term, use day.after(n) or day.before(n) in a loop to iterate through days until hasJieQi() returns true.

    if day.hasJieQi():
        idx = day.getJieQi()
        jd = day.getJieQiJD()
        # Convert JD to date object (Y, M, D, h, m, s)
        t = sxtwl.JD2DD(jd)
        print(f"Solar Term time: {t.Y}-{t.M}-{t.D} {t.h}:{t.m}:{round(t.s)}")
    
    # Finding the next solar term
    while True:
        day = day.after(1)
        if day.hasJieQi():
            break
  7. Perform Four Pillars (Si Zhu) reverse lookup

    master

    The function sxtwl.siZhu2Year() allows you to search for years within a specific range that match a given set of Four Pillars (Year, Month, Day, and Hour stems/branches). It returns a list of Julian Days that satisfy the criteria.

    Note: You must provide sxtwl.GZ(tg_index, dz_index) objects for the stems and branches.

    # Example: Search for years between 2003 and 2029 matching specific pillars
    # Arguments: Year GZ, Month GZ, Day GZ, Hour GZ, Start Year, End Year
    jds = sxtwl.siZhu2Year(
        sxtwl.GZ(0, 1), # Example Year GZ
        sxtwl.GZ(5, 2), # Example Month GZ
        sxtwl.GZ(2, 3), # Example Day GZ
        sxtwl.GZ(9, 4), # Example Hour GZ
        2003, 2029
    )
    
    for jd in jds:
        t = sxtwl.JD2DD(jd)
        print(f"Match found: {t.Y}-{t.M}-{t.D}")
  8. Calculate Lunar Month details and Leap Months

    master

    Use the following utility functions for lunar calculations:

    • Get Leap Month of a year: sxtwl.getRunMonth(year) returns the month index if it's a leap month, or a value < 0 if there is no leap month.
    • Get number of days in a lunar month: sxtwl.getLunarMonthNum(year, month, isRun) where isRun is a boolean indicating if the month is a leap month.
    # Get leap month for 2020
    month = sxtwl.getRunMonth(2020)
    
    # Get days in lunar month (Year 2020, Month 4, not a leap month)
    daynum = sxtwl.getLunarMonthNum(2020, 4, False)
  9. Retrieve Solar and Lunar calendar information

    master

    Once you have a day object, you can query various attributes:

    • Solar Info: getSolarYear(), getSolarMonth(), getSolarDay().
    • Lunar Info: getLunarYear(), getLunarMonth(), getLunarDay(), isLunarLeap().
    • Week Info: getWeek() (returns index for day of week), getWeekIndex() (returns week of the month).
    • Zodiac: getConstellation() (returns index for Western zodiac).

    Lunar Year Boundaries:

    • getLunarYear(True) (or no argument): Uses the Spring Festival as the boundary for the lunar year.
    • getLunarYear(False): Uses Li Chun (Start of Spring) as the boundary for the lunar year.
    # Solar date
    print(day.getSolarYear(), day.getSolarMonth(), day.getSolarDay())
    
    # Week of the month
    print(day.getWeekIndex())
    
    # Lunar date (Spring Festival boundary)
    print(day.getLunarYear(), 'Leap' if day.isLunarLeap() else '', day.getLunarMonth(), day.getLunarDay())
    
    # Lunar date (Li Chun boundary)
    print(day.getLunarYear(False), day.getLunarMonth(), day.getLunarDay())