WMeshGms.mjs

import fs from 'fs'
import get from 'lodash-es/get.js'
import map from 'lodash-es/map.js'
import each from 'lodash-es/each.js'
import drop from 'lodash-es/drop.js'
import split from 'lodash-es/split.js'
import values from 'lodash-es/values.js'
import min from 'lodash-es/min.js'
import max from 'lodash-es/max.js'
import sep from 'wsemi/src/sep.mjs'
import cint from 'wsemi/src/cint.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'


function readXyz(fp) {
    // bottomleft_x, bottomleft_y, bottomleft_z, size_x, size_y, size_z
    // 311500.0, 2722500.0, -20.0, 100, 100, 1
    let c = fs.readFileSync(fp, 'utf8')
    let ss = sep(c, '\n')
    ss = drop(ss, 1)
    let lines = map(ss, (s) => {
        return split(s, ',')
    })
    let line = get(lines, 0, [])
    let kp = {
        blx: cdbl(get(line, 0, 0)),
        bly: cdbl(get(line, 1, 0)),
        z: cdbl(get(line, 2, 0)),
        sx: cdbl(get(line, 3, 0)),
        sy: cdbl(get(line, 4, 0)),
        sz: cdbl(get(line, 5, 0)),
    }
    return kp
}


function readMat(fp) {
    // no, "id", "k", "i", "j", "f"
    // 1, 1, 1, 1, 1, 1
    // 2, 2, 1, 1, 2, 1
    // 3, 3, 1, 1, 3, 1
    let c = fs.readFileSync(fp, 'utf8')
    let ss = sep(c, '\n')
    ss = drop(ss, 1)
    let lines = map(ss, (s) => {
        return split(s, ',')
    })
    let kp = {}
    each(lines, (v) => {
        let id = cint(get(v, 1, 0))
        let k = cint(get(v, 2, 0))
        let i = cint(get(v, 3, 0))
        let j = cint(get(v, 4, 0))
        let mat = cint(get(v, 5, 0))
        kp[id] = { id, i, j, k, mat }
    })
    return kp
}


function readTopBot(fp, key) {
    // no, "id", "k", "i", "j", "f", "Active"
    // 1, 1, 1, 1, 1, 29.0, 0
    // 2, 2, 1, 1, 2, 29.0, 0
    // 3, 3, 1, 1, 3, 29.0, 0
    let c = fs.readFileSync(fp, 'utf8')
    let ss = sep(c, '\n')
    ss = drop(ss, 1)
    let lines = map(ss, (s) => {
        return split(s, ',')
    })
    let kp = {}
    each(lines, (v) => {
        let id = cint(get(v, 1, 0))
        let k = cint(get(v, 2, 0))
        let i = cint(get(v, 3, 0))
        let j = cint(get(v, 4, 0))
        let value = cdbl(get(v, 5, 0))
        let active = cint(get(v, 6, 0))
        kp[id] = {
            id,
            i,
            j,
            k,
            [key]: value,
            active,
        }
    })
    return kp
}


/**
 * 讀取GMS的ASCII檔
 *
 * @param {String} fp 輸入檔案位置字串
 * @return {Promise} 回傳Promise,resolve回傳ltdt(各數據列為物件陣列),reject回傳錯誤訊息
 * @example
 *
 * let fpXyz = './_mesh/YiLan_xyz.txt'
 * let fpTop = './_mesh/YiLan_top.txt'
 * let fpBot = './_mesh/YiLan_bot.txt'
 * let fpMat = './_mesh/YiLan_mat.txt'
 * wmg.readGms(fpXyz, fpTop, fpBot, fpMat)
 *     .then((res) => {
 *         console.log(res)
 *         console.log('finish.')
 *     })
 *     .catch((err) => {
 *         console.log(err)
 *     })
 *
 */
async function readGms(fpXyz, fpTop, fpBot, fpMat) {

    // console.log('reading...xyz')
    let vxyz = readXyz(fpXyz)
    // console.log('vxyz', vxyz)

    // console.log('reading...top')
    let vtop = readTopBot(fpTop, 'top')
    // console.log('vtop[1]', vtop[1])

    // console.log('reading...bot')
    let vbot = readTopBot(fpBot, 'bot')
    // console.log('vbot[1]', vbot[1])

    // console.log('reading...mat')
    let vmat = readMat(fpMat)
    // console.log('vmat[1]', vmat[1])

    //merge
    // console.log('merging...')
    let kpEle = {}
    each(vmat, (v, id) => {
        let top = get(vtop, `${id}.top`, 0)
        let bot = get(vbot, `${id}.bot`, 0)
        let active = get(vbot, `${id}.active`, 0)
        let key = `${v.i}-${v.j}-${v.k}`
        kpEle[key] = {
            id: v.id,
            i: v.i,
            j: v.j,
            k: v.k,
            top,
            bot,
            mat: v.mat,
            active,
        }
    })
    // console.log(`kpEle['1-1-1']`, kpEle['1-1-1'])

    //_eles
    let _eles = values(kpEle)

    //min, max
    let _is = map(_eles, 'i')
    let iMin = min(_is)
    let iMax = max(_is)
    let _js = map(_eles, 'j')
    let jMin = min(_js)
    let jMax = max(_js)
    let _ks = map(_eles, 'k')
    let kMin = min(_ks)
    let kMax = max(_ks)

    //nodes, kpNode
    let nodes = []
    let kpNode = {}
    if (true) {

        let indn = 0
        for (let _k = kMax; _k >= kMin; _k--) {
            for (let i = iMin; i <= iMax; i++) {
                for (let j = jMin; j <= jMax; j++) {

                    let k = kMax - _k + 1
                    let keyOri = `${i}-${j}-${_k}`
                    let keyNew = `${i}-${j}-${k}`

                    let ele = get(kpEle, keyOri, {})

                    //將元素視為左下節點(tecplot的節點才可給參數), 故座標須平移半格, i,j最末端不處理, 因此x,y向長寬會少sx與sy
                    let x = vxyz.blx + (i + 0.5) * vxyz.sx
                    let y = vxyz.bly + (j + 0.5) * vxyz.sy
                    let z = get(ele, 'bot', 0)
                    let mat = get(ele, 'mat', 0)
                    let active = get(ele, 'active', 0)

                    indn++
                    let node = {
                        indn,
                        key: keyNew,
                        x,
                        y,
                        z,
                        mat, //tecplot的節點才可給參數
                        active,
                    }
                    nodes.push(node)
                    kpNode[keyNew] = node

                    //若為最頂部, 則取top出來添加節點
                    if (_k === kMin) {

                        keyNew = `${i}-${j}-${k + 1}`

                        z = get(ele, 'top', 0)

                        indn++
                        let node = {
                            indn,
                            key: keyNew,
                            x,
                            y,
                            z,
                            mat, //tecplot的節點才可給參數
                            active,
                        }
                        nodes.push(node)
                        kpNode[keyNew] = node

                    }

                }
            }
        }

    }
    // console.log('nodes[0]', nodes[0])
    // console.log(`kpNode['1-1-1']`, kpNode['1-1-1'])

    //eles
    let eles = []
    if (true) {

        //將元素視為左下節點, 故座標須平移半格, i,j,k最末端不處理, 因此x,y向元素各-1
        let inde = 0
        for (let _k = kMax; _k >= kMin; _k--) {
            for (let i = iMin; i <= iMax - 1; i++) {
                for (let j = jMin; j <= jMax - 1; j++) {

                    let k = kMax - _k + 1
                    let key000 = `${i}-${j}-${k}`
                    let key100 = `${i + 1}-${j}-${k}`
                    let key110 = `${i + 1}-${j + 1}-${k}`
                    let key010 = `${i}-${j + 1}-${k}`
                    let key001 = `${i}-${j}-${k + 1}`
                    let key101 = `${i + 1}-${j}-${k + 1}`
                    let key111 = `${i + 1}-${j + 1}-${k + 1}`
                    let key011 = `${i}-${j + 1}-${k + 1}`

                    let active000 = get(kpNode, `${key000}.active`, 0)
                    let active100 = get(kpNode, `${key100}.active`, 0)
                    let active110 = get(kpNode, `${key110}.active`, 0)
                    let active010 = get(kpNode, `${key010}.active`, 0)
                    let active001 = get(kpNode, `${key001}.active`, 0)
                    let active101 = get(kpNode, `${key101}.active`, 0)
                    let active111 = get(kpNode, `${key111}.active`, 0)
                    let active011 = get(kpNode, `${key011}.active`, 0)
                    let active = active000 + active100 + active110 + active010 + active001 + active101 + active111 + active011
                    if (active !== 8) {
                        continue
                    }

                    inde++
                    let ele = {
                        inde,
                        // kds: {
                        //     key000,
                        //     key100,
                        //     key110,
                        //     key010,
                        //     key001,
                        //     key101,
                        //     key111,
                        //     key011,
                        // },
                        nodes: [
                            get(kpNode, `${key000}.indn`, 0),
                            get(kpNode, `${key100}.indn`, 0),
                            get(kpNode, `${key110}.indn`, 0),
                            get(kpNode, `${key010}.indn`, 0),
                            get(kpNode, `${key001}.indn`, 0),
                            get(kpNode, `${key101}.indn`, 0),
                            get(kpNode, `${key111}.indn`, 0),
                            get(kpNode, `${key011}.indn`, 0),
                        ],
                        mat: get(kpNode, `${key000}.mat`, 0),
                    }
                    eles.push(ele)

                }
            }
        }

    }
    // console.log('eles[0]', eles[0])

    return {
        nodes,
        eles,
    }
}


/**
 * 輸出數據至GMS檔案
 *
 * @param {String} fp 輸入檔案位置字串
 * @param {Array} data 輸入數據陣列,為mat或ltdt格式
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {String} [opt.mode='ltdt'] 輸入數據格式字串,可選ltdt或mat,預設ltdt
 * @param {Array} [opt.keys=[]] 輸入指定欲輸出鍵值陣列,預設[]
 * @param {Object} [opt.kphead={}] 輸入指定鍵值轉換物件,預設{}
 * @return {Promise} 回傳Promise,resolve回傳成功訊息,reject回傳錯誤訊息
 * @example
 *

 *
 */
async function writeGms(fp, nodes, eles, opt = {}) {

    console.log('尚待開發')

    return null
}

/**
 * 讀寫GMS的ASCII檔檔
 *
 * @return {Object} 回傳物件,其內有readGms與writeGms函式
 * @example
 *

 *
 */
let WMeshGms = {
    readGms,
    writeGms,
}


export default WMeshGms