// File: /workspace/github_cpp_makefile_star2_O1/rurban[P]dgnlib/dgnwrite.cpp
// Function: DGNCreateCellHeaderFromGroup
DGNElemCore *
DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName, 
                              short nClass, short *panLevels, 
                              int nNumElems, DGNElemCore **papsElems,
                              DGNPoint *psOrigin, 
                              double dfXScale, double dfYScale,
                              double dfRotation )

{
    int         nTotalLength;
    int         i, nLevel;
    DGNElemCore *psCH;
    DGNPoint    sMin={0.0,0.0,0.0}, sMax={0.0,0.0,0.0};
    unsigned char abyLevelsOccuring[8] = {0,0,0,0,0,0,0,0};
    DGNInfo *psInfo = (DGNInfo *) hDGN;

    DGNLoadTCB( hDGN );

    if( nNumElems < 1 || papsElems == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Need at least one element to form a cell." );
        return NULL;
    }

    if( psInfo->dimension == 2 )
        nTotalLength = 27;
    else
        nTotalLength = 43;

/* -------------------------------------------------------------------- */
/*      Collect the total size, and bounds.                             */
/* -------------------------------------------------------------------- */

    for( i = 0; i < nNumElems; i++ )
    {
        DGNPoint sThisMin, sThisMax;
        int  nLevel;

        nTotalLength += papsElems[i]->raw_bytes / 2;

        /* mark as complex */
        papsElems[i]->complex = TRUE;
        papsElems[i]->raw_data[0] |= 0x80;

        /* establish level */
        nLevel = papsElems[i]->level;
        abyLevelsOccuring[nLevel >> 3] |= (0x1 << ((nLevel-1)&0x7));
        
        DGNGetElementExtents( hDGN, papsElems[i], &sThisMin, &sThisMax );
        if( i == 0 )
        {
            sMin = sThisMin;
            sMax = sThisMax;
        }
        else
        {
            sMin.x = MIN(sMin.x,sThisMin.x);
            sMin.y = MIN(sMin.y,sThisMin.y);
            sMin.z = MIN(sMin.z,sThisMin.z);
            sMax.x = MAX(sMax.x,sThisMax.x);
            sMax.y = MAX(sMax.y,sThisMax.y);
            sMax.z = MAX(sMax.z,sThisMax.z);
        }
    }

/* -------------------------------------------------------------------- */
/*      It seems that the range needs to be adjusted according to       */
/*      the rotation and scaling.                                       */
/*                                                                      */
/*      NOTE: Omitting code ... this is already done in                 */
/*      DGNInverseTransformPoint() called from DGNWriteBounds().        */
/* -------------------------------------------------------------------- */
#ifdef notdef
    sMin.x -= psOrigin->x;
    sMin.y -= psOrigin->y;
    sMin.z -= psOrigin->z;
    sMax.x -= psOrigin->x;
    sMax.y -= psOrigin->y;
    sMax.z -= psOrigin->z;

    sMin.x /= ((DGNInfo *) hDGN)->scale;
    sMin.y /= ((DGNInfo *) hDGN)->scale;
    sMin.z /= ((DGNInfo *) hDGN)->scale;
    sMax.x /= ((DGNInfo *) hDGN)->scale;
    sMax.y /= ((DGNInfo *) hDGN)->scale;
    sMax.z /= ((DGNInfo *) hDGN)->scale;
#endif

/* -------------------------------------------------------------------- */
/*      Create the corresponding cell header.                           */
/* -------------------------------------------------------------------- */
    if( panLevels == NULL )
        panLevels = (short *) abyLevelsOccuring + 0;

    psCH = DGNCreateCellHeaderElem( hDGN, nTotalLength, pszName, 
                                    nClass, panLevels, 
                                    &sMin, &sMax, psOrigin, 
                                    dfXScale, dfYScale, dfRotation );
    DGNWriteBounds( (DGNInfo *) hDGN, psCH, &sMin, &sMax );
    
    return psCH;
    
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movsd %xmm2, 0x70(%rsp)
movsd %xmm1, 0x68(%rsp)
movsd %xmm0, 0x60(%rsp)
movq %r9, %r12
movl %r8d, %ebp
movq %rcx, %r13
movl %edx, %r15d
movq %rsi, %r14
movq %rdi, %rbx
xorpd %xmm0, %xmm0
movapd %xmm0, 0x30(%rsp)
xorl %eax, %eax
movq %rax, 0x40(%rsp)
movq %rax, 0x20(%rsp)
movapd %xmm0, 0x10(%rsp)
movq %rax, 0x48(%rsp)
callq 0xb37c
testl %ebp, %ebp
setg %al
testq %r12, %r12
setne %cl
testb %cl, %al
jne 0xe607
leaq 0x35f6(%rip), %rdx      # 0x11be4
xorl %r14d, %r14d
movl $0x3, %edi
movl $0x1, %esi
xorl %eax, %eax
callq 0x46dc
jmp 0xe7ad
movq %r13, 0x50(%rsp)
movl %r15d, 0xc(%rsp)
movq %r14, 0x58(%rsp)
xorl %r13d, %r13d
cmpl $0x2, 0x20018(%rbx)
setne %r13b
shll $0x4, %r13d
addl $0x1b, %r13d
movl %ebp, %r15d
xorl %r14d, %r14d
movq (%r12,%r14,8), %rax
movl 0x40(%rax), %ebp
movl $0x1, %ecx
movl %ecx, 0x18(%rax)
movq 0x48(%rax), %rax
orb $-0x80, (%rax)
movq (%r12,%r14,8), %rsi
movl 0x10(%rsi), %eax
leal -0x1(%rax), %ecx
andb $0x7, %cl
movl $0x1, %edx
shll %cl, %edx
sarl $0x3, %eax
cltq
orb %dl, 0x48(%rsp,%rax)
movq %rbx, %rdi
leaq 0x90(%rsp), %rdx
leaq 0x78(%rsp), %rcx
callq 0x8c32
testq %r14, %r14
je 0xe6fc
movsd 0x30(%rsp), %xmm0
movsd 0x38(%rsp), %xmm1
minsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
minsd 0x98(%rsp), %xmm1
movsd %xmm1, 0x38(%rsp)
movsd 0x40(%rsp), %xmm0
minsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movsd 0x10(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
maxsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
maxsd 0x80(%rsp), %xmm1
movsd %xmm1, 0x18(%rsp)
movsd 0x20(%rsp), %xmm0
maxsd 0x88(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
jmp 0xe72f
movq 0xa0(%rsp), %rax
movq %rax, 0x40(%rsp)
movups 0x90(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
movupd 0x78(%rsp), %xmm0
movapd %xmm0, 0x10(%rsp)
movq 0x88(%rsp), %rax
movq %rax, 0x20(%rsp)
movl %ebp, %eax
shrl $0x1f, %eax
addl %ebp, %eax
sarl %eax
addl %eax, %r13d
incq %r14
cmpq %r14, %r15
jne 0xe632
movq 0x50(%rsp), %rax
testq %rax, %rax
leaq 0x48(%rsp), %r8
cmovneq %rax, %r8
leaq 0x10(%rsp), %r15
movswl 0xc(%rsp), %ecx
leaq 0x30(%rsp), %r12
movq %rbx, %rdi
movl %r13d, %esi
movq 0x58(%rsp), %rdx
movq %r12, %r9
movsd 0x60(%rsp), %xmm0
movsd 0x68(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
pushq 0xe0(%rsp)
pushq %r15
callq 0xe1d9
addq $0x10, %rsp
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
movq %r12, %rdx
movq %r15, %rcx
callq 0xc80f
movq %r14, %rax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq