# Path: pam/pam.py
# SEED = 0
#     SEED = bpy.context.scene.pam_mapping.seed
# def computeUVScalingFactor(obj):
# def map3dPointToParticle(obj, particle_system, location):
# def maskParticle(p_layer, p_index, mask_layer, distance=0.2):
# def distanceToMask(p_layer, p_index, particle_index, mask_layer):
# def computeConnectivityProbability(uv1, uv2, func, args):
# def computeDistance_PreToSynapse(no_connection, pre_index, synapses=[]):
# def sortNeuronsToUV(layer, neuronset, u_or_v):
# def computeMapping(layers, connections, distances, point, debug=False):
# def computeDistanceToSynapse(ilayer, slayer, p_3d, s_2d, dis):
# def addConnection(*args):
# def replaceMapping(index, connection):
# def computeAllConnections():
# def updateMapping(index):
# def computeConnectivity(con, create=True, threads = None):
# def post_neuron_wrapper(x):
# def post_neuron_initializer(players, pconnections, pdistances):
# def pre_neuron_wrapper(x):
# def pre_neuron_initializer(players, pconnections, pdistances, puv_grid, pno_synapses):
# def computeConnectivityThreaded(con, create=True, threads = None):
# def computeConnectivityAll(layers, neuronset1, neuronset2, slayer, connections, distances, func, args):
# def printConnections():
# def computeDistance(layer1, layer2, neuronset1, neuronset2, common_layer,
#                     connection_matrix):
# def measureUVs(objects):
# def initializeUVs():
# def returnNeuronGroups():
# def resetOrigins():
# def initialize3D():


import mstree
import mst_blender
import numpy as np
import bpy
import mathutils
from pam import pam

def create_uv_tree(obj, quantity, uv_center, mean = [0.0, 0.0], variance = [0.005, 0.005], balancing_factor = 0.0, build_type = 'CURVE', interpolation_resolution = 0):

    # Generate scattered points
    x = [uv_center[0]]
    y = [uv_center[1]]
    x = np.concatenate((x, np.random.normal(uv_center[0], variance[0], quantity) + mean[0]))
    y = np.concatenate((y, np.random.normal(uv_center[1], variance[1], quantity) + mean[1]))

    points = np.dstack((x, y))
    np.clip(points, 0., 1., out = points)
    # all items are stored in the first list-item of the output
    points = points[0]
    
    # Run mstree
    root_point = mstree.mstree(points, balancing_factor)

    # Convert node positions from uv to 3d
    nodes = mstree.tree_to_list(root_point)
    
    interpolated_nodes = []
    for node in nodes:
        parent = node.parent
        interpolated_nodes.append(node)
        if parent is None:
            continue

# Path: pam/pam.py
# SEED = 0
#     SEED = bpy.context.scene.pam_mapping.seed
# def computeUVScalingFactor(obj):
# def map3dPointToParticle(obj, particle_system, location):
# def maskParticle(p_layer, p_index, mask_layer, distance=0.2):
# def distanceToMask(p_layer, p_index, particle_index, mask_layer):
# def computeConnectivityProbability(uv1, uv2, func, args):
# def computeDistance_PreToSynapse(no_connection, pre_index, synapses=[]):
# def sortNeuronsToUV(layer, neuronset, u_or_v):
# def computeMapping(layers, connections, distances, point, debug=False):
# def computeDistanceToSynapse(ilayer, slayer, p_3d, s_2d, dis):
# def addConnection(*args):
# def replaceMapping(index, connection):
# def computeAllConnections():
# def updateMapping(index):
# def computeConnectivity(con, create=True, threads = None):
# def post_neuron_wrapper(x):
# def post_neuron_initializer(players, pconnections, pdistances):
# def pre_neuron_wrapper(x):
# def pre_neuron_initializer(players, pconnections, pdistances, puv_grid, pno_synapses):
# def computeConnectivityThreaded(con, create=True, threads = None):
# def computeConnectivityAll(layers, neuronset1, neuronset2, slayer, connections, distances, func, args):
# def printConnections():
# def computeDistance(layer1, layer2, neuronset1, neuronset2, common_layer,
#                     connection_matrix):
# def measureUVs(objects):
# def initializeUVs():
# def returnNeuronGroups():
# def resetOrigins():
# def initialize3D():


# Path: pam/trees/uv_tree.py
import mstree
import mst_blender
import numpy as np
import bpy
import mathutils
from pam import pam


def create_uv_tree(obj, quantity, uv_center, mean = [0.0, 0.0], variance = [0.005, 0.005], balancing_factor = 0.0, build_type = 'CURVE', interpolation_resolution = 0):

    # Generate scattered points
    x = [uv_center[0]]
    y = [uv_center[1]]
    x = np.concatenate((x, np.random.normal(uv_center[0], variance[0], quantity) + mean[0]))
    y = np.concatenate((y, np.random.normal(uv_center[1], variance[1], quantity) + mean[1]))

    points = np.dstack((x, y))
    np.clip(points, 0., 1., out = points)
    # all items are stored in the first list-item of the output
    points = points[0]
    
    # Run mstree
    root_point = mstree.mstree(points, balancing_factor)

    # Convert node positions from uv to 3d
    nodes = mstree.tree_to_list(root_point)
    
    interpolated_nodes = []
    for node in nodes:
        parent = node.parent
        interpolated_nodes.append(node)
        if parent is None:
            continue

        points = interpolate(parent.pos, node.pos, interpolation_resolution)[1:-1]