#!/usr/bin/env python
# _*_ coding: utf-8 _*_

"""
 <File Description>

 File Name : set_mp_line_arrays.py

 Author : Kim Ki-hwan (wbkifun@korea.ac.kr)
          Kim, KyoungHo (rain_woo@korea.ac.kr)

 Written date : 2008. 3. 19

 Copyright : GNU GPL

============================== < File Description > ===========================

Define the functions for conformal line arrays.
    set_mp_line_arrays
    set_overlap_boundary_grid_line

===============================================================================
"""

from structure_base import *

def set_mp_line_arrays(structures, MP_line_arrays):
    #--------------------------------------------------------------------------
    # grid-line value for single region
    #--------------------------------------------------------------------------
    for structure in structures:
        DER = structure.discretized_effective_region
        ISPTs_arrays = structure.intersection_points_arrays
        MP = list(structure.matter)[1:]

        for axis in [x_axis, y_axis, z_axis]:
            axis_list = [x_axis, y_axis, z_axis]
            axis_list.pop(axis)
            i_axis, j_axis = axis_list

            for i in xrange( DER[i_axis*2], DER[i_axis*2+1] ):
                for j in xrange( DER[j_axis*2], DER[j_axis*2+1] ):
                    slice_indices = [i,j]
                    i0, j0 = DER[i_axis*2], DER[j_axis*2]
                    x1 = ISPTs_arrays[axis][0][i-i0,j-j0]
                    x2 = ISPTs_arrays[axis][1][i-i0,j-j0]

                    for m, MP_line_array in enumerate(MP_line_arrays):
                        if int(x1) != int(x2):
                            # main grid-line
                            slice_indices.insert( axis, slice(int(x1)+1, int(x2)) )
                            MP_line_array[axis][ tuple(slice_indices) ] = MP[m]

                            # boundary grid-line
                            slice_indices.insert( axis, int(x1) )
                            MP_line_array[axis][ tuple(slice_indices) ] = MP[m]*(1-x1%1)

                            slice_indices.insert( axis, int(x2) )
                            MP_line_array[axis][ tuple(slice_indices) ] = MP[m]*(x2%1)
                        else:
                            # boundary grid-line
                            slice_indices.insert( axis, int(x1) )
                            MP_line_array[axis][ tuple(slice_indices) ] = MP[m]*( x2-x1 )

    #--------------------------------------------------------------------------
    # grid-line value for overlap region
    #--------------------------------------------------------------------------
    for k, structure1 in enumerate(structures):
        DER1 = structure1.discretized_effective_region
        DERS1 = structure1.discretized_effective_region_sides
        DERC1 = structure1.discretized_effective_region_center

        for structure2 in structures[k+1:]:
            DER2 = structure2.discretized_effective_region
            DERS2 = structure2.discretized_effective_region_sides
            DERC2 = structure2.discretized_effective_region_center

            distance_center = abs( DERC2[:] - DERC1[:] )

            is_overlap = True
            for axis in [x_axis, y_axis, z_axis]:
                if (DERS1[axis] + DERS2[axis]) <= 2*distance_center[axis]:
                    is_overlap = False

            if is_overlap:
                ODER = overlap_DER = []
                for axis in [x_axis, y_axis, z_axis]:
                    ODER.append( [ \
                            DER1[axis*2], DER1[axis*2+1], \
                            DER2[axis*2], DER2[axis*2+1] ] )
                    ODER[-1].sort()

                ODER = [ ODER[0][1], ODER[0][2], \
                         ODER[1][1], ODER[1][2], \
                         ODER[2][1], ODER[2][2] ]

                set_mp_overlap_boundary_grid_line( \
                        MP_line_arrays, ODER, structure1, structure2 )


def set_mp_overlap_boundary_grid_line( \
        MP_line_arrays, ODER, structure1, structure2):
    ISPTs_arrays1 = structure1.intersection_points_arrays
    ISPTs_arrays2 = structure2.intersection_points_arrays
    MP1 = list(structure1.matter)[1:]
    MP2 = list(structure2.matter)[1:]

    for axis in [x_axis, y_axis, z_axis]:
        axis_list = [x_axis, y_axis, z_axis]
        axis_list.pop(axis)
        i_axis, j_axis = axis_list

        for i in xrange( ODER[i_axis*2], ODER[i_axis*2+1] ):
            for j in xrange( ODER[j_axis*2], ODER[j_axis*2+1] ):
                slice_indices = [i,j]
                i0, j0 = DER1[i_axis*2], DER1[j_axis*2]
                x1 = ISPTs_arrays1[axis][0][i-i0,j-j0]
                x2 = ISPTs_arrays1[axis][1][i-i0,j-j0]

                i0, j0 = DER2[i_axis*2], DER2[j_axis*2]
                x3 = ISPTs_arrays2[axis][0][i-i0,j-j0]
                x4 = ISPTs_arrays2[axis][1][i-i0,j-j0]

                d1, d2 = x2-x1, x4-x3 # distance between 2 points
                c1, c2 = x1+0.5*d1, x3+0.5*d2 # center between 2 points

                # non-overlap cell
                if 2*abs(c1-c2) >= abs(d1+d2):
                    for m, MP_line_array in enumerate(MP_line_arrays):

                        if int(x2) == int(x3):
                            slice_indices.insert( axis, int(x2) )
                            sd1, sd2 = (x2%1), (1-x3%1) # small distance

                            if sd1 + sd2 >= 1:
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        (MP2[m]-MP1[m])*sd2 + MP1[m]
                            elif sd1 + sd2 < 1:
                                MP_base = ( MP_line_array[axis][ \
                                        tuple(slice_indices) ] - \
                                        MP2[m]*sd2 )/(1-sd2)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        MP1[m]*sd1 + MP2[m]*sd2 + \
                                        (1-sd1-sd2)*MP_base

                        elif int(x4) == int(x1):
                            slice_indices.insert( axis, int(x4) )
                            sd2, sd1 = (x4%1), (1-x1%1) # small distance

                            if sd1 + sd2 >= 1: 
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        (MP2[m]-MP1[m])*sd2 + MP1[m]
                            elif sd1 + sd2 < 1:
                                MP_base = ( MP_line_array[axis][ \
                                        tuple(slice_indices) ] - \
                                        MP2[m]*sd2 )/(1-sd2)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        MP1[m]*sd1 + MP2[m]*sd2 + \
                                        (1-sd1-sd2)*MP_base


                # fully included overlap cell
                elif 2*abs(c1-c2) < abs(d1-d2): 
                    for m, MP_line_array in enumerate(MP_line_arrays):
                        if x4 < x2:
                            if int(x1) == int(x3):
                                slice_indices.insert( axis, int(x3) )
                                sd1, sd2 = (1-x1%1), (1-x3%1)
                                MP_base = ( MP_line_array[axis][ \
                                        tuple(slice_indices) ] - \
                                        MP2[m]*sd2 )/(1-sd2)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        MP1[m]*(sd1-sd2) + MP2[m]*sd2 + \
                                        (1-sd1)*MP_base
                            else:
                                slice_indices.insert( axis, int(x3) )
                                sd2 = (1-x3%1)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        (MP2[m]-MP1[m])*sd2 + MP1[m]

                            if int(x2) == int(x4):
                                slice_indices.insert( axis, int(x4) )
                                sd1, sd2 = (x2%1), (x4%1)
                                MP_base = ( MP_line_array[axis][ \
                                        tuple(slice_indices) ] - \
                                        MP2[m]*sd2 )/(1-sd2)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        MP1[m]*(sd1-sd2) + MP2[m]*sd2 + \
                                        (1-sd1)*MP_base
                            else:
                                slice_indices.insert( axis, int(x4) )
                                sd2 = (x4%1)
                                MP_line_array[axis][ tuple(slice_indices) ] = \
                                        (MP2[m]-MP1[m])*sd2 + MP1[m]


                # partially included overlap cell
                elif 2*abs(c1-c2) < abs(d1+d2) and 2*abs(c1-c2) >= abs(d1-d2): 
                    for m, MP_line_array in enumerate(MP_line_arrays):
                        if x4 >= x2:
                            slice_indices.insert( axis, int(x3) )
                            sd2 = (1-x3%1)
                            MP_line_array[axis][ tuple(slice_indices) ] = \
                                    (MP2[m]-MP1[m])*sd2 + MP1[m]
                        else:
                            slice_indices.insert( axis, int(x4) )
                            MP_line_array[axis][ tuple(slice_indices) ] = (MP2[m]-MP1[m])*( x4%1 ) + MP1[m]


def overlap_distance(d1, d2, cx1, cx2):
    D = abs
