\chapter{Control Structures}

To make our code capable representing any computation, certain control structures are required. We need a way of running a particular command conditionally on some other information. And we need a way of executing the same code more than once.

\section{if-else}

\index{if}

Conditional execution in JavaScript is implemented using the if-else structure, or just called an if-statement. To use an if-statement I first need a quantity that reduces to a boolean value: either true or false. This value becomes the condition under which a particular piece of code is executed if it is true. The condition is placed between the set of open and closed parenthesis. Immediately following the parenthesis is the piece of code that will be executed if the condition is true. The code is grouped together using an open-closed set of curly brackets.

\codejs{\source{js/if_true.js}}

I can also specify that something is done if the value is \textit{not} true, which will fall under the \texttt{else} part. Not true is the same as saying false.

\codejs{\source{js/if_nottrue.js}}

Even though the above example is completely valid, it can be simplified since there are no operations done in the top part of the if-else. I can use the logical 'not', \texttt{!}, to negate the boolean values. True becomes false, and false becomes true. This flips the roles of the if-else blocks, and so I can get rid of the 'else' part, while keeping the same logic. That is, this version of the control structure is equivalent to the previous one.

\codejs{\source{js/if_nottrue2.js}}

In the following example, I am testing to see if a particular number is even or odd, and I want it to print something different in each case. To see if a number is even, I used the modulus operator. If the number divided by 2 has a zero remainder, then the modulus will return zero, and I know that 2 is a factor of the number. The \texttt{===} operator returns true if \texttt{myNumber \% 2} is zero, and false if it is not zero. You should always give an if-statement a boolean value, and so comparison operators can be used to convert numbers to booleans. The comparison has the lowest order of operations, and so it will be done last.\\

\codejs{\source{js/odd.js}}

All of the operations together, \texttt{myNumber \% 2 === 0}, becomes the condition of the if-statement. Only the first thing following the condition is associated with the 'true' case. The piece of code immediately following the else is not executed if the condition is true, but it is if the condition is false. If you wish to have multiple commands associated with the condition, curly braces are used to group the code together.\\

\codejs{\source{js/odd_2.js}}

Here I not only print out whether the number is even, but divide it by two if it is even. If it is odd, I subtract 1 from the number before dividing so that the result is still an integer. If I had not put curly braces around each set of code, then the interpreter would not have understood that I wanted the second statement in each block to only be executed for that condition.\\

\section{nested if-else}

Any code can be placed in an if-statement, including more if-statements. A common problem is that a variable could have several possible values, and something different should happen for each value.

\codejs{\source{js/hello_foo.js}}

The first if-statement checks for one value. If it is that value it does the thing it should for it. If it's not that value, it goes to the \texttt{else} part. The only thing in the else of the first if-statement is another if-statement that checks for another value. If it's the second value it does that thing, but if it's not it goes to the else of the second if-statement.\\

However, any structure of nested if-else statements is valid.

\codejs{\source{js/ifrainy.js}}

What will be printed above given the values of \texttt{daylight}, \texttt{clouds}, and \texttt{rain}? Does the value of \texttt{lights} affect what's printed, or when would it? What would the values have to be in order for them to decide to "go swimming"?\\

Certain logic can sometimes be expressed in more that one way. Boolean algebra can be used to rewrite if-else structures into a series of equivalent  if-statements using the logical operators.

\codejs{\source{js/ifrainy2.js}}

While this is logically equivalent to the first structure, it checks and rechecks the same values at each if-statement. It is also harder to see which scenarios, or cases, have a prescribed activity. And what if a \texttt{!} was accidentally omitted? While the choice of which types of structures to use is up to you, your choice should be guided by both the purpose of the structure, and how easy it is to understand and debug if it doesn't work as expected.\\

Let's look at exactly how an if-else can be re-written with logical operators, or vice-versa. A single 'and' operation can be thought of as a nested if-else statement where both conditions have to be true for the result to be true. If either condition is false (or both), the result is false. The two if-else structures in the following example are equivalent.

\index{and}

\codejs{\source{js/and.js}}

For an 'or' operation, if at least one of the conditions is true (or both), then the result is true. This can be represented by a series of if-else statements. The only time the result is false is if both conditions are false.

\index{or}

\codejs{\source{js/or.js}}

These kind of examples also help to explain what is called short-circuit behavior in boolean operators. Take a look back at the 'and' example. If the value of \texttt{a} was false, then the first if-else structure would never even check the value \texttt{b} because it would have immediately gone to the else part. The same is true with the \texttt{\&\&} operator. If \texttt{a} is false, then the value of \texttt{b} doesn't matter and so it doesn't check it. For the \texttt{||} operator, if the first value is true, then the value of the second doesn't matter since only one of them has to be true for the result to be true.\\

It may seem like we don't need to worry about short circuit behavior as programmers, since why should we care if it checks a value or not. For the most part it doesn't matter for writing programs. However, if you make a function call in the condition of an if-statement, short-circuit behavior could matter if that function call does something in addition to being a condition.

\section{while}

\index{while loop}

The iteration control structure has to be tied to a conditional structure, so that it knows when to stop. A \texttt{while} loop initially behaves similarly to an if-statement. The condition is placed in the parenthesis immediately following the \texttt{while} keyword. If the condition is false, then execution skips the code in the braces. If the condition is true, it executes the code in the braces, but after it's done it re-evaluates the condition. It continues to execute the code in the braces, and evaluates the condition, until the condition is false.\\

\codejs{\source{js/countto5.js}}

In the above example, the variable \texttt{x} is called the loop control variable. Its initial value of \texttt{0} causes the condition \texttt{x < 5} to be true, and so it then executes the code in the braces. The only thing it does is to add 1 to the variable. It then checks the condition again, which is still true. It keeps repeating this process adding 1 to \texttt{x} each time, until it gets to 5. When \texttt{x} is 5, the condition becomes false since 5 is not less than 5. The loop executed the code a total of 5 times before it stopped.\\

A loop will continue to repeat itself for as long as the condition is true. If nothing occurs to cause the condition to be false, the loop will run for as long as the program is capable: this is called an infinite loop.\\

\codejs{\source{js/infiniteloop.js}}

The above example will run forever, even though it might look very similar to the first example. The issue is that the variable being changed inside the loop is different than the variable being used in the condition. \texttt{x < 5} will always be true, and thus it will loop forever.\\

A while loop does not necessarily have to proceed in a linear fashion. How many times does the following loop repeat, and what is the final value of \texttt{x}?

\codejs{\source{js/powersof2loop.js}}

Consider the following loop as a brain teaser.

\codejs{\source{js/zigzagloop.js}}

Does this loop ever stop? If so, how many times does it loop? Just by looking at the terminating condition, and assuming it does stop eventually, what must be the final value of \texttt{x}?

\section{for}

\index{for loop}

The 'for' loop is a shorter way of writing a linear while loop. If I know ahead of time exactly how many times I want the loop to repeat, there is a regular pattern I can follow. First, create a variable that starts at zero. The loop condition is as long as that variable is less than the number of times I want it to loop. And after each loop I add 1 to the variable.

\codejs{\source{js/countto5for.js}}

When you write a for loop, the stuff inside the parenthesis is not just the loop condition. It also contains the initial value of the loop control variable, and the increment operation done after each time through the loop. In every other way this for loop works exactly the same as the while loop. It loops exactly 5 times.\\

Now, what numbers get printed to the console? The first time through the loop the value of \texttt{x} is 0, so 0 gets printed. The 1, 2, 3, and 4. After it prints the 4 the increment \texttt{x++} adds 1 to x, making it 5. But \texttt{5 < 5} is false, and so the loop doesn't repeat. Even though the final value is 5, it never gets printed.


\documentclass[11pt,oneside]{article}    %use"amsart"insteadof"article"forAMSLaTeXformat
\usepackage{geometry}        %Seegeometry.pdftolearnthelayoutoptions.Therearelots.
\geometry{letterpaper}        %...ora4paperora5paperor...
%\geometry{landscape}        %Activateforforrotatedpagegeometry
%\usepackage[parfill]{parskip}        %Activatetobeginparagraphswithanemptylineratherthananindent
\usepackage{graphicx}                %Usepdf,png,jpg,orepsßwithpdflatex;useepsinDVImode
                                %TeXwillautomaticallyconverteps-->pdfinpdflatex
\usepackage{amssymb}
\usepackage[colorlinks]{hyperref}

%----macros begin---------------------------------------------------------------
\usepackage{color}
\usepackage{amsthm}

\def\conv{\mbox{\textrm{conv}\,}}
\def\aff{\mbox{\textrm{aff}\,}}
\def\E{\mathbb{E}}
\def\R{\mathbb{R}}
\def\Z{\mathbb{Z}}
\def\tex{\TeX}
\def\latex{\LaTeX}
\def\v#1{{\bf #1}}
\def\p#1{{\bf #1}}
\def\T#1{{\bf #1}}

\def\vet#1{{\left(\begin{array}{cccccccccccccccccccc}#1\end{array}\right)}}
\def\mat#1{{\left(\begin{array}{cccccccccccccccccccc}#1\end{array}\right)}}

\def\lin{\mbox{\rm lin}\,}
\def\aff{\mbox{\rm aff}\,}
\def\pos{\mbox{\rm pos}\,}
\def\cone{\mbox{\rm cone}\,}
\def\conv{\mbox{\rm conv}\,}
\newcommand{\homog}[0]{\mbox{\rm homog}\,}
\newcommand{\relint}[0]{\mbox{\rm relint}\,}

%----macros end-----------------------------------------------------------------

\title{Accelerated intersection of geometric objects
\footnote{This document is part of the \emph{Linear Algebraic Representation with CoChains} (LAR-CC) framework~\cite{cclar-proj:2013:00}. \today}
}
\author{Alberto Paoluzzi}
%\date{}                            %Activatetodisplayagivendateornodate

\begin{document}
\maketitle
\nonstopmode

\begin{abstract}
This module contains the first experiments of a parallel implementation of the intersection of (multidimensional) geometric objects. The first installment is being oriented to the intersection of line segment in the 2D plane. A generalization of the algorithm, based on the classification of the containment boxes of the geometric values, will follow quickly.
\end{abstract}

\tableofcontents

%===============================================================================
\section{Introduction}
%===============================================================================

An easily parallelizable implementation of the accelerated intersection of geometric objects is given in this module. Our first aim is to implement a specialized version for simplices, that generalizes the $nD$-trees of points (that are 0-simplices), to $(d-1)$-dimensional simplices in $d$-space, starting with the intersection of line segments in the plane. Our plan is to follow with an implementation for intersection of general \emph{non convex} sets.

%===============================================================================
\section{Implementation}
%===============================================================================

The first implementation of this module concerns the computation of the intersection points among a set of line segment in the 2D plane. The containment boxes of the input segments are iteratively classified against the 1-dimensional centroid of smaller and smaller buckets of data.

At the end of the classification, where the same geometric object may be inserted in several different buckets, a \emph{brute-force} intersection is applied to each final subset. Finally, the duplicated intersection points are removed, and a 1-dimensional LAR data structure is generated, with 1-cells given by the split line segments.

A complete LAR of the plane partition generated by the arrangment of lines is then computed by: (a) generating the maximal 2-connected components of such 1-dimensional graph; and (b) by traversing in counter-clockwise order the generated subgraphs to report the 2-dimensional cells of the plane partition.

The splitting algorithm may be easily parallelized, since both during their generation and at the end of this one, the various buckets of data can be dispatched to different processors for independent computation, followed by elimination of duplicates. In particular, a standard \emph{map-reduce} software infrastructure may be used for this parallelization purpose.

\subsection{Construction of independent buckets}
%===============================================================================

\paragraph{Containment boxes}

Given as input a list \texttt{randomLineArray} of pairs of 2D points, the function \texttt{containment2DBoxes} returns, in the same order, the list of \emph{containment boxes} of the input lines. A \emph{containment box} of a geometric object of dimension $d$ is defined as the minimal $d$-cuboid, equioriented with the reference frame, that contains the object. For a 2D line it is given by the tuple $(x1,y1,x2,y2)$, where $(x1,y1)$ is the point of minimal coordinates, and $(x2,y2)$ is the point of maximal  coordinates.

%-------------------------------------------------------------------------------
@D Containment boxes
@{""" Containment boxes """
def containment2DBoxes(randomLineArray):
    boxes = [eval(vcode(4)([min(x1,x2),min(y1,y2),max(x1,x2),max(y1,y2)]))
            for ((x1,y1),(x2,y2)) in randomLineArray]
    return boxes
@}
%-------------------------------------------------------------------------------

\paragraph{Splitting the input above and below a threshold}
%-------------------------------------------------------------------------------
@D Splitting the input above and below a threshold
@{""" Splitting the input above and below a threshold """
def splitOnThreshold(boxes,subset,coord):
    theBoxes = [boxes[k] for k in subset]
    threshold = centroid(theBoxes,coord)
    ncoords = len(boxes[0])/2
    a = coord%ncoords
    b = a+ncoords
    below,above = [],[]
    for k in subset:
        if boxes[k][a] <= threshold: below += [k]
    for k in subset:
        if boxes[k][b] >= threshold: above += [k]
    return below,above
@}
%-------------------------------------------------------------------------------

\paragraph{Iterative splitting of box buckets}
%-------------------------------------------------------------------------------
@D Iterative splitting of box buckets
@{""" Iterative splitting of box buckets """
def splitting(bucket,below,above, finalBuckets,splittingStack):
    if (len(below)<4 and len(above)<4) or len(set(bucket).difference(below))<7 \
        or len(set(bucket).difference(above))<7:
        finalBuckets.append(below)
        finalBuckets.append(above)
    else:
        splittingStack.append(below)
        splittingStack.append(above)

def geomPartitionate(boxes,buckets):
    geomInters = [set() for h in range(len(boxes))]
    for bucket in buckets:
        for k in bucket:
            geomInters[k] = geomInters[k].union(bucket)
    for h,inters in enumerate(geomInters):
        geomInters[h] = geomInters[h].difference([h])
    return AA(list)(geomInters)

def boxBuckets(boxes):
    bucket = range(len(boxes))
    splittingStack = [bucket]
    finalBuckets = []
    while splittingStack != []:
        bucket = splittingStack.pop()
        below,above = splitOnThreshold(boxes,bucket,1)
        below1,above1 = splitOnThreshold(boxes,above,2)
        below2,above2 = splitOnThreshold(boxes,below,2)
        splitting(above,below1,above1, finalBuckets,splittingStack)
        splitting(below,below2,above2, finalBuckets,splittingStack)
        finalBuckets = list(set(AA(tuple)(finalBuckets)))
    parts = geomPartitionate(boxes,finalBuckets)
    return AA(sorted)(parts)
@}
%-------------------------------------------------------------------------------

\subsection{Brute force intersection within the buckets}
%===============================================================================

\paragraph{Intersection of two line segments}
%-------------------------------------------------------------------------------
@D Intersection of two line segments
@{""" Intersection of two line segments """
def segmentIntersect(boxes,lineArray,pointStorage):
    def segmentIntersect0(h):
        p1,p2 = lineArray[h]
        line1 = '['+ vcode(4)(p1) +','+ vcode(4)(p2) +']'
        (x1,y1),(x2,y2) = p1,p2
        B1,B2,B3,B4 = boxes[h]
        def segmentIntersect1(k):
            p3,p4 = lineArray[k]
            line2 = '['+ vcode(4)(p3) +','+ vcode(4)(p4) +']'
            (x3,y3),(x4,y4) = p3,p4
            b1,b2,b3,b4 = boxes[k]
            if not (b3<B1 or B3<b1 or b4<B2 or B4<b2):
            #if True:
                m23 = mat([p2,p3])
                m14 = mat([p1,p4])
                m = m23 - m14
                v3 = mat([p3])
                v1 = mat([p1])
                v = v3-v1
                a=m[0,0]; b=m[0,1]; c=m[1,0]; d=m[1,1];
                det = a*d-b*c
                if det != 0:
                    m_inv = mat([[d,-b],[-c,a]])*(1./det)
                    alpha, beta = (v*m_inv).tolist()[0]
                    #alpha, beta = (v*m.I).tolist()[0]
                    if -0.0<=alpha<=1 and -0.0<=beta<=1:
                        pointStorage[line1] += [alpha]
                        pointStorage[line2] += [beta]
                        return list(array(p1)+alpha*(array(p2)-array(p1)))
            return None
        return segmentIntersect1
    return segmentIntersect0
@}
%-------------------------------------------------------------------------------

\paragraph{Brute force bucket intersection}
%-------------------------------------------------------------------------------
@D Brute force bucket intersection
@{""" Brute force bucket intersection """
def lineBucketIntersect(boxes,lineArray, h,bucket, pointStorage):
    intersect0 = segmentIntersect(boxes,lineArray,pointStorage)
    intersectionPoints = []
    intersect1 = intersect0(h)
    for line in bucket:
        point = intersect1(line)
        if point != None:
            intersectionPoints.append(eval(vcode(4)(point)))
    return intersectionPoints
@}
%-------------------------------------------------------------------------------

\paragraph{Accelerate intersection of lines}
%-------------------------------------------------------------------------------
@D Accelerate intersection of lines
@{""" Accelerate intersection of lines """
def lineIntersection(lineArray):
    lineArray = [line for line in lineArray if len(line)>1]
    from collections import defaultdict
    pointStorage = defaultdict(list)
    for line in lineArray:
        p1,p2 = line
        key = '['+ vcode(4)(p1) +','+ vcode(4)(p2) +']'
        pointStorage[key] = []
    boxes = containment2DBoxes(lineArray)
    buckets = boxBuckets(boxes)
    intersectionPoints = set()
    for h,bucket in enumerate(buckets):
        pointBucket = lineBucketIntersect(boxes,lineArray, h,bucket, pointStorage)
        intersectionPoints = intersectionPoints.union(AA(tuple)(pointBucket))
    frags = AA(eval)(pointStorage.keys())
    params = AA(COMP([sorted,list,set,tuple,eval,vcode(4)]))(pointStorage.values())
    return intersectionPoints,params,frags  ### GOOD: 1, WRONG: 2 !!!
@}
%-------------------------------------------------------------------------------

\subsection{Generation of LAR representation of split segments}
%===============================================================================
The function \texttt{lines2lar} is used to generate a 1-dimensional LAR complex from
an array of lines, i.e.~of pairs of 2D points. For every \emph{line} in \texttt{frags}
is computed an \emph{ordered} list \texttt{outline} of \emph{symbolic} intersection points, including
the first and last vertex of the line, and every interior point generated by the list \texttt{params[k]}.

Then, for every symbolic representation \texttt{key} of a point in \texttt{outline}, a
dictionary vertex is either created or retrieved, and a corresponding edge is orderly created, using the index of the point.
At the same time, the vertices created in this way are accumulated within the \texttt{V} array.
Finally, each edge in EV is extended to contain a second vertex index using the subsequent edge.

The third stage finalizes the vertex set of the output LAR, by identifying the closest vertices, i.e.~those at distance
less or equal to the current resolution, set to \texttt{10**(-PRECISION)}, by searching via the \texttt{scipy.spatialKDTree} the pairs of vertices at less than this distance.

A fourth stage identifies the possibly duplicated edges. Some of these could appear, e.g., when importing a set of adjacent boxes from some drawing program, to generate an array of lines, to be mutually intersected and transformed into a LAR data structure.

\paragraph{Create the LAR of fragmented lines}
%-------------------------------------------------------------------------------
@D Create the LAR of fragmented lines
@{""" Create the LAR of fragmented lines """
from scipy import spatial

def lines2lar(lineArray,normalize=False):
    _,params,frags = lineIntersection(lineArray)
    vertDict = dict()
    index,defaultValue,V,EV = -1,-1,[],[]

    for k,(p1,p2) in enumerate(frags):
        outline = [vcode(4)(p1)]
        if params[k] != []:
            for alpha in params[k]:
                if alpha != 0.0 and alpha != 1.0:
                    p = list(array(p1)+alpha*(array(p2)-array(p1)))
                    outline += [vcode(4)(p)]
        outline += [vcode(4)(p2)]

        edge = []
        for key in outline:
            if vertDict.get(key,defaultValue) == defaultValue:
                index += 1
                vertDict[key] = index
                edge += [index]
                V += [eval(key)]
            else:
                edge += [vertDict[key]]
            EV.extend([[edge[k],edge[k+1]] for k,v in enumerate(edge[:-1])])

    model = (V,EV)
    if normalize == True:
         model = larModelNormalization(model)
    return larSimplify(model)
@}
%-------------------------------------------------------------------------------

\subsection{Biconnected components of a 1-complex}
%===============================================================================

An implementation of the Hopcroft-Tarjan algorithm~\cite{Hopcroft:1973:AEA:362248.362272} for computation of the biconnected components of a graph is given here.

\paragraph{Biconnected components}
%-------------------------------------------------------------------------------
@D Biconnected components
@{""" Biconnected components """
@< Adjacency lists of 1-complex vertices @>
@< Main procedure for biconnected components @>
@< Hopcroft-Tarjan algorithm @>
@< Output of biconnected components @>
@}
%-------------------------------------------------------------------------------

\paragraph{Adjacency lists of 1-complex vertices}
%-------------------------------------------------------------------------------
@D Adjacency lists of 1-complex vertices
@{""" Adjacency lists of 1-complex vertices """
import larcc
def vertices2vertices(model):
    V,EV = model
    csrEV = larcc.csrCreate(EV)
    csrVE = larcc.csrTranspose(csrEV)
    csrVV = larcc.matrixProduct(csrVE,csrEV)
    cooVV = csrVV.tocoo()
    data,rows,cols = AA(list)([cooVV.data, cooVV.row, cooVV.col])
    triples = zip(data,rows,cols)
    VV = [[] for k in range(len(V))]
    for datum,row,col in triples:
        if row != col: VV[col] += [row]
    return AA(sorted)(VV)
@}
%-------------------------------------------------------------------------------

\paragraph{Main procedure for biconnected components}
%-------------------------------------------------------------------------------
@D Main procedure for biconnected components
@{""" Main procedure for biconnected components """
def biconnectedComponent(model):
    W,_ = model
    V = range(len(W))
    count = 0
    stack,out = [],[]
    visited = [None for v in V]
    parent = [None for v in V]
    d = [None for v in V]
    low = [None for v in V]
    for u in V: visited[u] = False
    for u in V: parent[u] = []
    VV = vertices2vertices(model)
    for u in V:
        if not visited[u]:
            DFV_visit( VV,out,count,visited,parent,d,low,stack, u )
    return W,[component for component in out if len(component) > 1]
@}
%-------------------------------------------------------------------------------

\paragraph{Hopcroft-Tarjan algorithm}
%-------------------------------------------------------------------------------
@D Hopcroft-Tarjan algorithm
@{""" Hopcroft-Tarjan algorithm """
def DFV_visit( VV,out,count,visited,parent,d,low,stack,u ):
    visited[u] = True
    count += 1
    d[u] = count
    low[u] = d[u]
    for v in VV[u]:
        if not visited[v]:
            stack += [(u,v)]
            parent[v] = u
            DFV_visit( VV,out,count,visited,parent,d,low,stack, v )
            if low[v] >= d[u]:
                out += [outputComp(stack,u,v)]
            low[u] = min( low[u], low[v] )
        else:
            if not (parent[u]==v) and (d[v] < d[u]):
                stack += [(u,v)]
                low[u] = min( low[u], d[v] )
@}
%-------------------------------------------------------------------------------

\paragraph{Output of biconnected components}
%-------------------------------------------------------------------------------
@D Output of biconnected components
@{""" Output of biconnected components """
def outputComp(stack,u,v):
    out = []
    while True:
        e = stack.pop()
        out += [list(e)]
        if e == (u,v): break
    return list(set(AA(tuple)(AA(sorted)(out))))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/biconnected1}
   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/biconnected2}

   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/biconnected3}
   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/biconnected4}
   \caption{Two random line arrangements, and the biconnected components extracted by their LAR 1-complexes.}
   \label{fig:biconnected}
\end{figure}

\subsection{2D cells from biconnected components}
%===============================================================================

It is very easy,  using the LAR representation of topology, to compute the 2-cells of the plane partitions~(see Figures~\ref{fig:biconnected}b and~\ref{fig:biconnected}c) induced by the biconnected components extracted from a graph (1-complex).

In particular, let us consider the CSR (Compressed Sparse Row) representation of the characteristic matrix $M_1$, here usually denoted as \texttt{EV}, in order to remark that we represent the edges on the rows, and the vertices on the columns of the matrix. As such it is a binary matrix. So, we can readily reconstruct the topology of 2-cells by associating to each non-zero (sparse) matrix element $\texttt{angle\_EV}(h,k)$ the angle in radians that the edge $e_h$ forms with the orizontal line, when it incides on the vertex $v_k$.

Of course, if $e_h = (v_{k_1},v_{k_2})$, then it will be
\[
\texttt{angle\_EV}(h,k_2) = \texttt{angle\_EV}(h,k_1)+\pi = -\texttt{angle\_EV}(h,k_1)
\]

Therefore, the columns of $\texttt{angle\_EV}$, i.e.~the rows of $\texttt{angle\_VE} := \texttt{angle\_EV}^t$,
after being sorted on their angles $\alpha$, and associated with the angle differences $\Delta\alpha$, will provide a basis of elementary $1-cochains$ that evaluate to zero for each closed 1-cochain, i.e. for every cycle supported by the linear space of 1-chains on the given line arrangment.

\paragraph{Slope of edges}

\paragraph{Circular ordering of edges around vertices}
%-------------------------------------------------------------------------------
@D Slope of edges
@{""" Circular ordering of edges around vertices """
from larcc import *

def edgeSlopeOrdering(model):
    V,EV = model
    VE,VE_angle = larcc.invertRelation(EV),[]
    for v,ve in enumerate(VE):
        ve_angle = []
        if ve != []:
            for edge in ve:
                v0,v1 = EV[edge]
                if v == v0:     x,y = list(array(V[v1]) - array(V[v0]))
                elif v == v1:    x,y = list(array(V[v0]) - array(V[v1]))
                angle = math.atan2(y,x)
                ve_angle += [180*angle/PI]
        pairs = sorted(zip(ve_angle,ve))
        #VE_angle += [TRANS(pairs)[1]]
        VE_angle += [[pair[1] for pair in pairs]]
    return VE_angle
@}
%-------------------------------------------------------------------------------

\paragraph{Ordered incidence relationship vertices to edges}

As we have seen, the \texttt{VE\_angle} list of lists reports, for every vertex in \texttt{V}, the list of incident edges, \emph{counterclockwise ordered} around the vertex. Therefore the \texttt{ordered\_csrVE} function, given below, returns the ``compressed sparse row'' matrix, row-indexed by vertices and column-indexed by edges, and such that in position $(v,e)$ contains the index $\ell$ of the next edge (after $e$, say) in the counterclockwise ordering of edges around $v$.

%-------------------------------------------------------------------------------
@D Ordered incidence relationship of vertices and edges
@{""" Ordered incidence relationship of vertices and edges """
def ordered_csrVE(VE_angle):
    triples = []
    for v,ve in enumerate(VE_angle):
        n = len(ve)
        for k,edge in enumerate(ve):
            triples += [[v, ve[k], ve[ (k+1)%n ]]]
    csrVE = triples2mat(triples,shape="csr")
    return csrVE
@}
%-------------------------------------------------------------------------------

\paragraph{Faces from biconnected components}
Since edges in the plane partition induced by a line arrangement are $(d-1)$-cells, they are located on the boundary of \emph{two} $d$-cells (faces) of the partition. Hence, the traversal algorithm of the data structure storing the relevant information may be driven by signing the two extremes (vertices) of each edge as either already visited or not.

%-------------------------------------------------------------------------------
@D Faces from biconnected components
@{""" Faces from biconnected components """

def firstSearch(visited):
    for edge,vertices in enumerate(visited):
        for v,vertex in enumerate(vertices):
            if visited[edge,v] == 0.0:
                visited[edge,v] = 1.0
                return edge,v
    return -1,-1

def facesFromComps(model):
    V,EV = model
    # Remove zero edges
    EV = list(set([ tuple(sorted([v1,v2])) for v1,v2 in EV if v1!=v2 ]))
    FV = []
    VE_angle = edgeSlopeOrdering((V,EV))
    csrEV = ordered_csrVE(VE_angle).T
    visited = zeros((len(EV),2))
    edge,v = firstSearch(visited)
    vertex = EV[edge][v]
    fv = []
    while True:
        if (edge,v) == (-1,-1):
            break #return [face for face in FV if face != None]
        elif (fv == []) or (fv[0] != vertex):

            fv += [vertex]
            nextEdge = csrEV[edge,vertex]
            v0,v1 = EV[nextEdge]

            try:
                vertex, = set([v0,v1]).difference([vertex])
            except ValueError:
                print 'ValueError: too many values to unpack'
                break

            if v0==vertex: pos=0
            elif v1==vertex: pos=1

            if visited[nextEdge, pos] == 0:
                visited[nextEdge, pos] = 1
                edge = nextEdge
        else:
            FV += [fv]
            fv = []
            edge,v = firstSearch(visited)
            vertex = EV[edge][v]
        FV = [face for face in FV if face != None]
    return V,FV,EV
@}
%-------------------------------------------------------------------------------

\paragraph{Txample}
The \emph{ordered} \texttt{csrVE} (vertex-edge) matrix generated by the example of file \texttt{test/py/inters/test07.py} is shown in dense format in the example script below.
Let us notice the each non-zero element $\texttt{csrVE}(k,h)$ stores the index of the previous edge
inciding on the vertex $v_k$ \emph{before} the edge $e_h$. The traversal of the data structure is made accordingly, in order to extract the vertices of all the faces (minimal edge cycles) generated by a line arrangement in the plane.

%-------------------------------------------------------------------------------
@D Example of VE matrix with nextEdge indices @{
csr2DenseMatrix(csrVE)
>>> array([
    [12,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 11,  0,  0,  0],
    [ 1,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
    [ 0, 14,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0],
    [ 0,  0,  6,  5,  0,  2,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0],
    [ 0,  0,  0, 10,  0,  0,  0,  0,  0,  3,  9,  0,  0,  0,  0,  0],
    [ 0,  0,  0,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  4],
    [ 0,  0,  0,  0, 12,  4,  0,  0,  0,  0,  0,  0,  5,  0,  0,  0],
    [ 0,  0,  0,  0,  0,  0,  7,  8,  6,  0,  0,  0,  0,  0,  0,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  8,  0,  0,  0,  0,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 13,  0, 14, 11,  0],
    [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0, 13]])
@}
%-------------------------------------------------------------------------------

\subsection{Transformation of an array of lines in a 2D LAR complex}
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

\paragraph{Transformation of an array of lines in a 2D LAR complex}

The whole transformation of an array of lines into a two-dimensional \texttt{LAR} complex is executed by the function \texttt{larFromLines}. The function returns the model triple \texttt{V,FV,EV}. The last element in \texttt{FV} is the \emph{ordered} boundary chain. just notice that

%    import networkx as nx
%    G=nx.Graph()
%    G.add_nodes_from(range(len(V)))
%    G.add_edges_from(EV)
%    g = [subgraph.edges() for subgraph in nx.biconnected_component_subgraphs(G, copy=True)
%            if len(subgraph.edges())>1]

%-------------------------------------------------------------------------------
@D Transformation of an array of lines in a 2D LAR complex @{
""" Transformation of an array of lines in a 2D LAR complex """
def larFromLines(lines,normalize=False):
    def larPairSimplify((V,EV)):
        V,EVs = biconnectedComponent((V,EV))
        EV = CAT(EVs)
        V,EV = larRemoveVertices(V,EV)
        return V,EV

    V,EV = lines2lar(lines,normalize)
    V,EV = larPairSimplify((V,EV))  #TODO:  toggle to check the generated FV
    V,polygons,EV = larPair2Triple((V,EV))
    FV = AA(list)(AA(set)(AA(CAT)(polygons)))
    return V,FV,EV,polygons
"""
def normalize(lines):
	vs = CAT(lines)
	xs,ys = TRANS(vs)
	w0,w1,w2,w3 = [min(xs), min(ys), max(xs), max(ys)]
	# viewport aspect-ratio checking, setting a computed-viewport 'v'
	ar = (w2-w0)/(w3-w1)
	if ar >1 : v0,v1,v2,v3 = 0,0,1,1./ar
	else: v0,v1,v2,v3 = 0,0,ar,1
	a,b,c,d = v2*w0, v3*w1, w2-w0, w3-w1
	M = mat(
	[[	v2/c,	0,	0 ],
	 [	0,	 v3/d,	0 ],
	 [	-a/c,-b/d,	1 ]])
	ws = [[x,y,1] for x,y in vs]
	W = (array(ws) * M)[:,:2].tolist()
	myLines = [[W[2*k],W[2*k+1]] for k in range(len(W)/2)]
	return myLines, M

def larFromLines(lines,normal=False):
    def larPairSimplify((V,EV)):
        V,EVs = biconnectedComponent((V,EV))
        EV = CAT(EVs)
        V,EV = larRemoveVertices(V,EV)
        return V,EV

    theLines,M = normalize(lines)
    V,EV = lines2lar(theLines,False)
    V,EV = larPairSimplify((V,EV))  #TODO:  toggle to check the generated FV
    V,polygons,EV = larPair2Triple((V,EV))
    FV = AA(list)(AA(set)(AA(CAT)(polygons)))
    if not normal:
    	W = (array([v+[1.0] for v in V]) * M.I)[:,:2].tolist()
    else: W = V
    return W,FV,EV,polygons
"""
@}
%-------------------------------------------------------------------------------

\subsection{Pruning LAR models from parts out of proper resolution}
%===============================================================================

Pruning of clusters of too close vertices is executed by taking a LAR model as input,
executing the following computations, and producing a new simplified LAR model.

\paragraph{Pruning away clusters of close vertices}
First, reduce the array of vertices \texttt{pts} to its \emph{quotient set} with respect to the transitive closure of the relation of ``nearness''. Two vertices are ``near'' when their (Euclidean) distance is less than a given \texttt{RADIUS}. The subgraphs of the graph of this relation are \emph{contracted} in a single point, set to the centroid of the vertices of the subgraph. The function \texttt{W} takes as input the array \texttt{pts} of vertex points, and returns: (a) the array \texttt{newV} of new vertices; (b) the list of lists \texttt{close} of sorted indices of pairs of close vertices, removed from duplicates; (c) the list of \texttt{clusters} of \texttt{pts} indices; (d) the integer  \texttt{vmap} array, mapping old vertex indices to new vertex indices.

%-------------------------------------------------------------------------------
@D Pruning away clusters of close vertices
@{""" Pruning away clusters of close vertices """
from scipy.spatial import cKDTree

def pruneVertices(pts,radius=0.001):
    tree = cKDTree(pts)
    a = cKDTree.sparse_distance_matrix(tree,tree,radius)
    #print a.keys()
    close = list(set(AA(tuple)(AA(sorted)(a.keys()))))
    import networkx as nx
    G=nx.Graph()
    G.add_nodes_from(range(len(pts)))
    G.add_edges_from(close)
    clusters, k, h = [], 0, 0

    subgraphs = list(nx.connected_component_subgraphs(G))
    V = [None for subgraph in subgraphs]
    vmap = [None for k in xrange(len(pts))]
    for k,subgraph in enumerate(subgraphs):
        #group = subgraph.nodes()
        group = list(subgraph.nodes())
        if len(group)>1:
            V[k] = CCOMB([pts[v] for v in group])
            for v in group: vmap[v] = k
            clusters += [group]
        else:
            oldNode = group[0]
            V[k] = pts[oldNode]
            vmap[oldNode] = k
    return V,close,clusters,vmap
@}
%-------------------------------------------------------------------------------

\paragraph{Export a simplified LAR model}
Next, update the arrays of compressed characteristic matrices of a Linear Algebraic Representation. The standard approach is to read row-wise the arrays of matrices of incidence of cells on vertices; translate every index using the \texttt{vmap} array, mapping old vertex indices to new ones; remove repeated indices and substitute them with a single instance; check if the new index list has lenght greater or equal to the number of vertices of the simplex of the proper dimension. Finally, write an output cell if and only if the previous test is true.

%-------------------------------------------------------------------------------
@D Return a simplified LAR model
@{""" Return a simplified LAR model """
def larSimplify(model,radius=0.001):
    if len(model)==2: V,CV = model
    elif len(model)==3: V,CV,FV = model
    else: print "ERROR: model input"

    W,close,clusters,vmap = pruneVertices(V,radius)
    celldim = DIM(MKPOL([V,[[v+1 for v in CV[0]]],None]))
    newCV = [list(set([vmap[v] for v in cell])) for cell in CV]
    CV = list(set([tuple(sorted(cell)) for cell in newCV if len(cell) >= celldim+1]))
    CV = sorted(CV,key=len) # to get the boundary cell as last one (in most cases)

    if len(model)==3:
        celldim = DIM(MKPOL([V,[[v+1 for v in FV[0]]],None]))
        newFV = [list(set([vmap[v] for v in facet])) for facet in FV]
        FV = [facet for facet in newFV if len(facet) >= celldim]
        FV = list(set(AA(tuple)(AA(sorted)(FV))))
        areas = integr.signedSurfIntegration((V,CV,FV),signed=False)
        CV = [CV[k] for k in range(len(CV)) if not isclose(areas[k],0.0)]
        return W,CV,FV
    else: return W,CV
@}
%-------------------------------------------------------------------------------

\paragraph{Test of pruning clusters of close vertices}
Here a list of random 2D points is generated. Then the set of vertices is pruned by updating it to its quotient set with respect to the transitive closure of a relation of ``nearness'' within an Euclidean distance of given \texttt{RADIUS}. The pruning of vertices is performed by the \texttt{pruneVertices} function, with input the array \texttt{pts} of points. The dictionary \texttt{vmap}
%-------------------------------------------------------------------------------
@O test/py/inters/test13.py
@{""" Test of pruning clusters of close vertices """
from larlib import *
from scipy import rand
from scipy.spatial import cKDTree
POINTS = 1000
RADIUS = 0.01

pts = [rand(2).tolist() for k in range(POINTS)]
VIEW(STRUCT(AA(MK)(pts)))
V,close,clusters,vmap = pruneVertices(pts,RADIUS)
circles = [T([1,2])(pts[h])(CIRCUMFERENCE(RADIUS)(18)) for h,k in close]
convexes = [JOIN(AA(MK)([pts[v] for v in cluster])) for cluster in clusters]
W = COLOR(CYAN)(STRUCT(AA(MK)(V)))
VIEW(STRUCT(AA(MK)(pts)+AA(COLOR(YELLOW))(circles)))
VIEW(STRUCT(AA(COLOR(RED))(convexes)+AA(MK)(pts)+AA(COLOR(YELLOW))(circles)+[W]))
@}
%-------------------------------------------------------------------------------

\paragraph{Test for exporting a simplified LAR model}

%-------------------------------------------------------------------------------
@O test/py/inters/test14.py
@{""" Test for exporting a simplified LAR model """
from larlib import *
filename = "test/svg/inters/closepoints.svg"
lines = svg2lines(filename)

V,EV = lines2lar(lines)
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,EV))))
pts = V
RADIUS = 0.05
V,close,clusters,vmap = pruneVertices(pts,RADIUS)
circles = [T([1,2])(pts[h])(CIRCUMFERENCE(RADIUS)(18)) for h,k in close]
convexes = [JOIN(AA(MK)([pts[v] for v in cluster])) for cluster in clusters]
W = COLOR(CYAN)(STRUCT(AA(MK)(V)))
VIEW(STRUCT(AA(COLOR(RED))(convexes)+AA(MK)(pts)+AA(COLOR(YELLOW))(circles)+[W]))

V,FV,EV,polygons = larFromLines(lines)
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,FV+EV)) + AA(MK)(V)))
VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,0.5))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test15.py
@{""" Testing containments between non intersecting cycles """
from larlib import *

filename = "test/svg/inters/facade.svg"
lines = svg2lines(filename)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,EV = lines2lar(lines)
V,EVs = biconnectedComponent((V,EV))
# candidate face
FVs = AA(COMP([list,set,CAT]))(EVs)

latticeArray = computeCycleLattice(V,EVs)

for k in range(len(latticeArray)):
    print k,latticeArray[k]

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FVs],submodel,0.15))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test16.py
@{""" Generating the LAR of a set of non-intersecting cycles """
from larlib import *

sys.path.insert(0, 'test/py/inters/')
from test15 import *

cells = cellsFromCycles(latticeArray)
CV = AA(COMP([list,set,CAT]))(EVs)
EVdict = dict(zip(EV,range(len(EV))))
FE = [[EVdict[edge] for edge in cycle] for cycle in EVs]
edges = [CAT([FE[cycle] for cycle in cell]) for cell in cells]
FVs = [[CV[cycle] for cycle in cell] for cell in cells]
FV = AA(CAT)(FVs)

n = len(cells)
chains = allBinarySubsetsOfLenght(n)

cycles = STRUCT(MKPOLS((V,EV)))
csrBoundaryMat = larBoundary(FV,EV)
for chain in chains:
    chainBoundary = COLOR(RED)(STRUCT(MKPOLS((V,[EV[e]
                        for e in chain2BoundaryChain(csrBoundaryMat)(chain)]))))
    VIEW(STRUCT([cycles, chainBoundary]))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test17.py
@{""" Generating the LAR of a set of non-intersecting cycles """
from larlib import *

sys.path.insert(0, 'test/py/inters/')
from test16 import *

lar = (V,FV,EV)

bcycles,_ = boundaryCycles(range(len(EV)),EV)
polylines = [[V[EV[e][1]] if e>0 else V[EV[-e][0]] for e in cycle ] for cycle in bcycles]
polygons = [polyline + [polyline[0]] for polyline in polylines]

complex = SOLIDIFY(STRUCT(AA(POLYLINE)(polygons)))
csrBoundaryMat = larBoundary(FV,EV)
for chain in chains:
    chainBoundary = COLOR(RED)(STRUCT(MKPOLS((V,[EV[e]
                        for e in chain2BoundaryChain(csrBoundaryMat)(chain)]))))
    VIEW(STRUCT([complex, chainBoundary]))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test18.py
@{""" Orienting a set of non-intersecting cycles """
from larlib import *

sys.path.insert(0, 'test/py/inters/')
from test17 import *

cells,bridgeEdges = connectTheDots((V,EV))
CVs = orientBoundaryCycles((V,EV),cells)

print "\nCVs =",CVs
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test19.py
@{""" Generating the LAR of a set of non-intersecting cycles """
from larlib import *

sys.path.insert(0, 'test/py/inters/')
from test17 import *

W,EW = boundaryCycles2vertexPermutation( (V,EV) )
VIEW(EXPLODE(1.2,1.2,1.2)(MKPOLS((W,EW))))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test20.py
@{""" Generating the Triangulation of a set of non-intersecting cycles """
from larlib import *

sys.path.insert(0, 'test/py/inters/')
from test17 import *

triangleSet = larTriangulation( (V,EV) )

VIEW(STRUCT(AA(JOIN)(AA(AA(MK))(CAT(triangleSet)))))
VIEW(SKEL_1(STRUCT(AA(JOIN)(AA(AA(MK))(CAT(triangleSet))))))

model = V,EV
W,FW = lar2boundaryPolygons(model)
polygons = [[W[u] for u in poly] for poly in FW]
VIEW(STRUCT(AA(POLYLINE)(polygons)))

triangleSet,triangledFace = [],[]
for polygon in polygons:
    triangledPolygon = []
    polyline = []
    for p in polygon:
        polyline.append(Point(p[0],p[1]))
    cdt = CDT(polyline)

    triangles = cdt.triangulate()
    trias = [ [[t.a.x,t.a.y,0],[t.c.x,t.c.y,0],[t.b.x,t.b.y,0]] for t in triangles ]
    triangleSet += [AA(REVERSE)(trias)]
@}
%-------------------------------------------------------------------------------

%===============================================================================
\section{Exporting the module}
%===============================================================================

%-------------------------------------------------------------------------------
@O larlib/larlib/inters.py
@{""" Module for pipelined intersection of geometric objects """
from larlib import *
from triangulation import *
from scipy import mat

@< Coding utilities @>
@< Generation of random lines @>
@< Containment boxes @>
@< Splitting the input above and below a threshold @>
@< Iterative splitting of box buckets @>
@< Intersection of two line segments @>
@< Brute force bucket intersection @>
@< Accelerate intersection of lines @>
@< Create the LAR of fragmented lines @>
@< Biconnected components @>
@< Slope of edges @>
@< Ordered incidence relationship of vertices and edges @>
@< Faces from biconnected components @>
@< SVG input parsing and transformation @>
@< Simplified SVG parsing and normalization @>
@< LAR 2D model normalization @>
@< Transformation of an array of lines in a 2D LAR complex @>
@< Pruning away clusters of close vertices @>
@< Return a simplified LAR model @>
@}
%-------------------------------------------------------------------------------

%===============================================================================
\section{Examples}
%===============================================================================

\paragraph{Generation of random line segments and their boxes}
%-------------------------------------------------------------------------------
@O test/py/inters/test01.py
@{""" Generation of random line segments and their boxes """
from larlib import *

randomLineArray = randomLines(200,0.3)
VIEW(STRUCT(AA(POLYLINE)(randomLineArray)))

boxes = containment2DBoxes(randomLineArray)
rects= AA(box2rect)(boxes)
cyan = COLOR(CYAN)(STRUCT(AA(POLYLINE)(randomLineArray)))
yellow = COLOR(YELLOW)(STRUCT(AA(POLYLINE)(rects)))
VIEW(STRUCT([cyan,yellow]))
@}
%-------------------------------------------------------------------------------

\paragraph{Split segment array in four independent buckets}
%-------------------------------------------------------------------------------
@O test/py/inters/test02.py
@{""" Split segment array in four independent buckets """
from larlib import *

randomLineArray = randomLines(200,0.3)
VIEW(STRUCT(AA(POLYLINE)(randomLineArray)))
boxes = containment2DBoxes(randomLineArray)
bucket = range(len(boxes))
below,above = splitOnThreshold(boxes,bucket,1)
below1,above1 = splitOnThreshold(boxes,above,2)
below2,above2 = splitOnThreshold(boxes,below,2)

cyan = COLOR(CYAN)(STRUCT(AA(POLYLINE)(randomLineArray[k] for k in below1)))
yellow = COLOR(YELLOW)(STRUCT(AA(POLYLINE)(randomLineArray[k] for k in above1)))
red = COLOR(RED)(STRUCT(AA(POLYLINE)(randomLineArray[k] for k in below2)))
green = COLOR(GREEN)(STRUCT(AA(POLYLINE)(randomLineArray[k] for k in above2)))

VIEW(STRUCT([cyan,yellow,red,green]))
@}
%-------------------------------------------------------------------------------

\paragraph{Generation and random coloring of independent line buckets}
%-------------------------------------------------------------------------------
@O test/py/inters/test03.py
@{""" Generation and random coloring of independent line buckets """
from larlib import *

lines = randomLines(200,0.3)
VIEW(STRUCT(AA(POLYLINE)(lines)))

boxes = containment2DBoxes(lines)
buckets = boxBuckets(boxes)

colors = [CYAN, MAGENTA, WHITE, RED, YELLOW, GRAY, GREEN, ORANGE, BLACK, BLUE, PURPLE, BROWN]
sets = [COLOR(colors[k%12])(STRUCT(AA(POLYLINE)([lines[h]
            for h in bucket]))) for k,bucket in enumerate(buckets) if bucket!=[]]

VIEW(STRUCT(sets))
@}
%-------------------------------------------------------------------------------

\paragraph{Construction of \texttt{LAR = (V,EV)} of random line arrangement}
%-------------------------------------------------------------------------------
@O test/py/inters/test04.py
@{""" LAR of random line arrangement """
from larlib import *

lines = randomLines(30,0.2)
VIEW(STRUCT(AA(POLYLINE)(lines)))

intersectionPoints,params,frags = lineIntersection(lines)

marker = CIRCLE(.005)([4,1])
markers = STRUCT(CONS(AA(T([1,2]))(intersectionPoints))(marker))
VIEW(STRUCT(AA(POLYLINE)(lines)+[COLOR(RED)(markers)]))

V,EV = lines2lar(lines)
marker = CIRCLE(.01)([4,1])
markers = STRUCT(CONS(AA(T([1,2]))(V))(marker))
#markers = STRUCT(CONS(AA(T([1,2]))(intersectionPoints))(marker))
polylines = STRUCT(MKPOLS((V,EV)))
VIEW(STRUCT([polylines]+[COLOR(MAGENTA)(markers)]))
@}
%-------------------------------------------------------------------------------

\paragraph{Splitting of othogonal lines}
%-------------------------------------------------------------------------------
@O test/py/inters/test05.py
@{""" LAR from splitting of othogonal lines """
from larlib import *
@< Orthogonal example @>
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@D Orthogonal example @{
lines = [[[0,0],[6,0]], [[0,4],[10,4]], [[0,0],[0,4]], [[3,0],[3,4]],
[[6,0],[6, 8]], [[3,2],[6,2]], [[10,0],[10,8]], [[0,8],[10,8]]]

VIEW(EXPLODE(1.2,1.2,1)(AA(POLYLINE)(lines)))

V,EV = lines2lar(lines)
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,EV))))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.25\linewidth,width=0.325\linewidth]{images/ortho1}
   \includegraphics[height=0.25\linewidth,width=0.325\linewidth]{images/ortho2}
   \includegraphics[height=0.25\linewidth,width=0.325\linewidth]{images/ortho3}
   \caption{Splitting of orthogonal lines: (a) exploded input; (a) exploded output; (c) biconnected components.}
   \label{fig:ortho}
\end{figure}

\paragraph{Random coloring of the generated 1-complex LAR}
%-------------------------------------------------------------------------------
@O test/py/inters/test06.py
@{""" Random coloring of the generated 1-complex """
from larlib import *

lines = randomLines(800,0.2)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,EV = lines2lar(lines)
colors = [CYAN, MAGENTA, WHITE, RED, YELLOW, GRAY, GREEN, ORANGE, BLACK, BLUE, PURPLE, BROWN]
sets = [COLOR(colors[k%12])(POLYLINE([V[e[0]],V[e[1]]])) for k,e in enumerate(EV)]

VIEW(STRUCT(sets))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[width=0.49\linewidth]{images/colored1}
   \includegraphics[width=0.49\linewidth]{images/colored2}
   \caption{Splitting of intersecting lines: (a) random input; (a) splitted and colored LAR output.}
   \label{fig:ortho}
\end{figure}

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/lineintersect1}
   \includegraphics[height=0.49\linewidth,width=0.49\linewidth]{images/lineintersect2}
   \caption{The intersection of 5000 random lines in the unit interval, with \texttt{scaling} parameter equal to \texttt{0.1}}
   \label{fig:example}
\end{figure}

\paragraph{Biconnected components from orthogonal LAR model}
%-------------------------------------------------------------------------------
@O test/py/inters/test07.py
@{""" Biconnected components from orthogonal LAR model """
from larlib import *
colors = [CYAN, MAGENTA, WHITE, RED, YELLOW, GREEN, ORANGE, BLACK, BLUE, PURPLE]

@< Orthogonal example @>
model = V,EV
V,EVs = biconnectedComponent(model)
HPCs = [STRUCT(MKPOLS((V,EV))) for EV in EVs]

sets = [COLOR(colors[k%10])(hpc) for k,hpc in enumerate(HPCs)]
VIEW(STRUCT(sets))
VIEW(STRUCT(MKPOLS((V,CAT(EVs)))))

#V,EV = larRemoveVertices(V,CAT(EVs))
@}
%-------------------------------------------------------------------------------

\paragraph{2-complex from orthogonal line segments}
%-------------------------------------------------------------------------------
@O test/py/inters/test08.py
@{""" 2-complex from orthogonal line segments """
from larlib import *
colors = [CYAN, MAGENTA, WHITE, RED, YELLOW, GREEN, ORANGE, BLACK, BLUE, PURPLE]

@< Orthogonal example @>
model = V,EV
V,EVs = biconnectedComponent(model)
HPCs = [STRUCT(MKPOLS((V,EV))) for EV in EVs]

sets = [COLOR(colors[k%10])(hpc) for k,hpc in enumerate(HPCs)]
VIEW(STRUCT(sets))

EV = sorted(CAT(EVs))
VIEW(STRUCT(MKPOLS((V,EV))))

V,FV,EV = facesFromComps((V,EV))

areas = surfIntegration((V,FV,EV))
boundaryArea = max(areas)
FV = [FV[f] for f,area in enumerate(areas) if area!=boundaryArea]
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,FV+EV)) + AA(MK)(V)))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d0}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d1}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d2}

   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d3}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d4}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/random2d5}
   \caption{\texttt{LAR} complex generation random lines. (a) the input random lines; (b) maximal biconnected graph extracted from the 1D LAR of intersected lines; (c) 2D cells of such \emph{regularized} 2-complex; (d) 2-cells, drawn exploded; (e) boundaries of 2D cells; (f) regularized cellular 2-complex extracted from lines.}
   \label{fig:ortho}
\end{figure}

\paragraph{Biconnected components from random LAR model}
%-------------------------------------------------------------------------------
@O test/py/inters/test09.py
@{""" Biconnected components from orthogonal LAR model """
from larlib import *
colors = [CYAN, MAGENTA, YELLOW, RED, GREEN, ORANGE, PURPLE, WHITE, BLACK, BLUE]

lines = randomLines(100,.8)
V,EV = lines2lar(lines)
model = V,EV
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,EVs = biconnectedComponent(model)
HPCs = [STRUCT(MKPOLS((V,EV))) for EV in EVs]
sets = [COLOR(colors[k%10])(hpc) for k,hpc in enumerate(HPCs)]
VIEW(STRUCT(sets))

EV = CAT(EVs)
V,EV = larRemoveVertices(V,EV)
V,FV,EV = facesFromComps((V,EV))
areas = surfIntegration((V,FV,EV))
boundaryArea = max(areas)
FV = [FV[f] for f,area in enumerate(areas) if area!=boundaryArea]

polylines = [[V[v] for v in face+[face[0]]] for face in FV]
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,EV)) + AA(MK)(V) + AA(FAN)(polylines) ))

colors = [CYAN, MAGENTA, WHITE, RED, YELLOW, GRAY, GREEN, ORANGE, BLACK, BLUE, PURPLE, BROWN]
sets = [COLOR(colors[k%12])(FAN(pol)) for k,pol in enumerate(polylines)]
VIEW(STRUCT(sets))

VIEW(EXPLODE(1.2,1.2,1)((AA(FAN)(polylines))))
VIEW(EXPLODE(1.2,1.2,1)((AA(POLYLINE)(polylines))))

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV],submodel,0.1))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/illustrator1}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/illustrator2}
   \includegraphics[height=0.325\linewidth,width=0.325\linewidth]{images/illustrator3}
   \caption{\texttt{LAR} complex generation from \texttt{SVG} file. (a) the input set of lines; (b) imported in \texttt{pyplasm} environment; (c) the extracted \emph{regularized} 2-complex, drawn exploded.}
   \label{fig:ortho}
\end{figure}

\paragraph{Simplified SVG parsing and normalization}
The easiest method for the input of SVG primitives, to be transformed into a \emph{line soup}, in order to subsiquently generate a 2D cellular complex, mainly oriented to sudent use, is to drag a SVG file into the input window of the web service \href{ http://cvdlab.github.io/svg2lines}{ http://cvdlab.github.io/svg2lines}.
The file is transformed into quadruples of comma-separated numbers, each corresponding to the pair of extreme point coordinates of a line.
This text may be saved into a text file, possibly decorated with the suffix \texttt{.lines}, to be read and normalized into the coordinate space $[0,1] \times [0,1]$ by the following function \texttt{lines2lines}, and then used by other
\texttt{larlib} functions (for example, by \texttt{lines2lar} (see \texttt{test/py/inters/test10.py}).

%-------------------------------------------------------------------------------
@D Simplified SVG parsing and normalization
@{""" Simplified SVG parsing and normalization """
def lines2lines(filename):
    stringLines = [line.strip() for line in open(filename)]
    lines = [AA(eval)(string.split(',')) for string in stringLines]
    lines = [[[x1,-y1],[x2,-y2]] for x1,y1,x2,y2 in lines]  # overturning y axis
    def stretch(line):
        c = CCOMB(line)
        L = mat(line)
        return (((L-c)*1.001)+c).tolist()
    lines  = [stretch(line) for line in lines]

    #< SVG input normalization transformation #>

    #V,EV = lines2lar(lines,normalize=True)
    #lines = [[ eval(vcode(5)(V[u])), eval(vcode(5)(V[v])) ] for u,v in EV]
    return lines
@}
%-------------------------------------------------------------------------------

\paragraph{SVG input parsing and transformation}

We postulate here that the input file \texttt{test/py/inters/test.svg} should contain only \texttt{<line>} primitives, so we skip any other content. Such primitives are parsed by matching against regular expressions, and their \texttt{x1,y1,x2,y2} attributes are extracted and stored into the \texttt{lines} variable.
An isomorphic window-viewport transformation is then performed, to transform the data within the standard unit 2D square $[0,1]^2$.
The input vertices are finally set to a fixed resolution, using the \texttt{vcode(4)} function.

%-------------------------------------------------------------------------------
@D SVG input parsing and transformation
@{""" SVG input parsing and transformation """
from larlib import *
import re # regular expression

def svg2lines(filename,containmentBox=[],rect2lines=True):
    stringLines = [line.strip() for line in open(filename)]

    # SVG <line> primitives
    lines = [string.strip() for string in stringLines if re.match("<line ",string)!=None]
    outLines = ""
    for line in lines:
        searchObj = re.search( r'(<line )(.+)(" x1=")(.+)(" y1=")(.+)(" x2=")(.+)(" y2=")(.+)("/>)', line)
        if searchObj:
            outLines += "[["+searchObj.group(4)+","+searchObj.group(6)+"], ["+searchObj.group(8) +","+ searchObj.group(10) +"]],"
    if lines != []:
        lines = list(eval(outLines))

    # SVG <rect> primitives
    rects = [string.strip() for string in stringLines if re.match("<rect ",string)!=None]
    outRects,searchObj = "",False
    for rect in rects:
        searchObj = re.search( r'(<rect x=")(.+?)(" y=")(.+?)(" )(.*?)( width=")(.+?)(" height=")(.+?)("/>)', rect)
        if searchObj:
            outRects += "[["+searchObj.group(2)+","+searchObj.group(4)+"], ["+searchObj.group(8)+","+searchObj.group(10)+"]],"

    if rects != []:
        rects = list(eval(outRects))
        if rect2lines:
            lines += CAT([[[[x,y],[x+w,y]],[[x+w,y],[x+w,y+h]],[[x+w,y+h],[x,y+h]],[[x,y+h],[x,y]]] for [x,y],[w,h] in rects])
        else:
            lines += [[[x,y],[x+w,y+h]] for [x,y],[w,h] in rects]

    lines = [[[p1[0],-p1[1]],[p2[0],-p2[1]]] for [p1,p2] in lines]  # overturning y axis

    #< SVG input normalization transformation #>
    #V,EV = larModelNormalization(lines2lar(lines))
    #lines = [[V[u],V[v]] for u,v in EV]

    containmentBox = box

    return lines
@}
%-------------------------------------------------------------------------------

\paragraph{LAR 2D model normalization}
%-------------------------------------------------------------------------------
@D LAR 2D model normalization
@{""" LAR 2D model normalization """
def larModelNormalization(model):
    V,EV = model
    xs,ys = TRANS(V)
    box = [min(xs), min(ys), max(xs), max(ys)]

    # viewport aspect-ratio checking, setting a computed-viewport 'b'
    b = [None for k in range(4)]
    if (box[2]-box[0])/(box[3]-box[1]) > 1:
        b[0]=0; b[2]=1;
        bm=(box[3]-box[1])/(box[2]-box[0]);
        b[1]=.5-bm/2; b[3]=.5+bm/2
    else:
        b[1]=0; b[3]=1;
        bm=(box[2]-box[0])/(box[3]-box[1]);
        b[0]=.5-bm/2; b[2]=.5+bm/2

    # isomorphic 'box -> b' transform to standard unit square
    W = [[ ((x1-box[0])*(b[2]-b[0]))/(box[2]-box[0]) ,
           ((y1-box[1])*(b[3]-b[1]))/(box[1]-box[3]) + 1]
        for [x1,y1] in V]
    return W,EV

def larModelNormalization(model):
    V,EV = model
    xs,ys = TRANS(V)
    w0,w1,w2,w3 = [min(xs), min(ys), max(xs), max(ys)]

    # viewport aspect-ratio checking, setting a computed-viewport 'v'
    ar = (w2-w0)/(w3-w1)
    if ar >1 : v0,v1,v2,v3 = 0,0,1,1./ar
    else: v0,v1,v2,v3 = 0,0,ar,1

    a,b,c,d = v2*w0, v3*w1, w2-w0, w3-w1
    W = [[(v2*x - a)/c, (v3*y - b)/d] for x,y in V]
    return W,EV
@}
%-------------------------------------------------------------------------------

\paragraph{SVG input normalization transformation}
The normalization transformation maps the input \texttt{lines} to the $[0,1]^2$ viewport, i.e. to the standard unit square.

%-------------------------------------------------------------------------------
@D SVG input normalization transformation
@{""" SVG input normalization transformation """
# window-viewport transformation
xs,ys = TRANS(CAT(lines))
box = [min(xs), min(ys), max(xs), max(ys)]

# viewport aspect-ratio checking, setting a computed-viewport 'b'
b = [None for k in range(4)]
if (box[2]-box[0])/(box[3]-box[1]) > 1:
    b[0]=0; b[2]=1; bm=(box[3]-box[1])/(box[2]-box[0]); b[1]=.5-bm/2; b[3]=.5+bm/2
else:
    b[1]=0; b[3]=1; bm=(box[2]-box[0])/(box[3]-box[1]); b[0]=.5-bm/2; b[2]=.5+bm/2

# isomorphic 'box -> b' transform to standard unit square
lines = [[[
((x1-box[0])*(b[2]-b[0]))/(box[2]-box[0]) ,
((y1-box[1])*(b[3]-b[1]))/(box[1]-box[3]) + 1], [
((x2-box[0])*(b[2]-b[0]))/(box[2]-box[0]),
((y2-box[1])*(b[3]-b[1]))/(box[1]-box[3]) + 1]]
      for [[x1,y1],[x2,y2]] in lines]

# line vertices set to fixed resolution
lines = eval("".join(['['+ vcode(4)(p1) +','+ vcode(4)(p2) +'], ' for p1,p2 in lines]))
@}
%-------------------------------------------------------------------------------

\paragraph{2-complex extraction from svg file}
The input \texttt{lines} arrangments produces a 1-dimensional complex stored into the \texttt{LAR} model \texttt{V,EV}. Then the \emph{dangling edges} are removed from \texttt{EV\_},
and the whole data set is renumbered, in order to remove the unused vertices, using the \texttt{larRemoveVertices} function.
Finally the 2-cells are computed and stored in \texttt{FV}, and the positive areas of every 2cells are computed, so allowing for identify and removal of the exterior face,
corresponding to the boundary of the complex.
The polygonal boundary of the complex is finally drawn.

%-------------------------------------------------------------------------------
@O test/py/inters/test10.py
@{""" Biconnected components from orthogonal LAR model """
from larlib import *

filename = "test/svg/inters/plan.svg"
#filename = "test/py/inters/building.svg"
#filename = "test/py/inters/complex.svg"
print
lines = svg2lines(filename)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,FV,EV,polygons = larFromLines(lines)
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,FV[:-1]+EV)) + AA(MK)(V)))

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV[:-1]],submodel,0.05))

verts,faces,edges = polyline2lar([[ V[v] for v in FV[-1] ]])
VIEW(STRUCT(MKPOLS((verts,edges))))
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test10a.py
@{""" Biconnected components from orthogonal LAR model """
from larlib import *

print "\n drag your SVG file to  http://cvdlab.github.io/svg2lines"
print "then save it to <path/filename>.lines"
filename = raw_input('filename =')

#filename = "test/svg/inters/plan.lines"
#filename = "test/py/inters/building.svg"
#filename = "test/py/inters/complex.svg"

lines = lines2lines(filename)
VIEW(STRUCT(AA(POLYLINE)(lines)))

V,FV,EV,polygons = larFromLines(lines)
VIEW(EXPLODE(1.2,1.2,1)(MKPOLS((V,FV[:-1]+EV)) + AA(MK)(V)))

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV[:-1]],submodel,0.05))

verts,faces,edges = polyline2lar([[ V[v] for v in FV[-1] ]])
VIEW(STRUCT(MKPOLS((verts,edges))))
@}
%-------------------------------------------------------------------------------

\begin{figure}[htbp] %  figure placement: here, top, bottom, or page
   \centering
   \includegraphics[height=0.2425\linewidth,width=0.2425\linewidth]{images/svg1}
   \includegraphics[height=0.2425\linewidth,width=0.2425\linewidth]{images/svg2}
   \includegraphics[height=0.2425\linewidth,width=0.2425\linewidth]{images/svg3}
   \includegraphics[height=0.2425\linewidth,width=0.2425\linewidth]{images/svg4}
   \caption{\texttt{LAR} complex generation from \texttt{SVG} file. (a) the input set of lines parsed from an \texttt{SVG} file; (b) the intersection of lines; (c) the extracted \emph{regularized} 2-complex, drawn exploded; (d) the boundary \texttt{LAR}.}
   \label{fig:ortho}
\end{figure}

%-------------------------------------------------------------------------------
@O test/py/inters/test11.py
@{""" Fast Polygon Triangulation based on Seidel's Algorithm """
# data generated by test10.py on file polygon.svg
from larlib import *

V,FV,EV = ([[0.222, 0.889],
  [0.722, 1.0],
  [0.519, 0.763],
  [1.0, 0.659],
  [0.859, 0.233],
  [0.382, 0.119],
  [0.519, 0.348],
  [0.296, 0.53],
  [0.0, 0.059]],
 [[0, 1, 2, 3, 4, 5, 6, 7, 8]],
 [[2, 3], [6, 7], [0, 8], [3, 4], [1, 2], [7, 8], [4, 5], [5, 6], [0, 1]])

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV],submodel,0.5))

xord = TRANS(sorted(zip(V,range(len(V)))))[1]
trapezoids = zip(xord[:-1],xord[1:])
vert2forw_trap = dict()
vert2back_trap = dict()

for k,(a,b) in enumerate(trapezoids[1:-1]):
    print k,(a,b)
    vert2back_trap[a]=k
    vert2forw_trap[a]=k+1
    vert2back_trap[b]=k+1
    vert2forw_trap[b]=k+2
vert2forw_trap[trapezoids[0][0]] = 0
vert2back_trap[trapezoids[-1][1]] = len(trapezoids)-1
@}
%-------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
@O test/py/inters/test12.py
@{""" Biconnected components from orthogonal LAR model """
from larlib import *

V = [[0.395, 0.296], [0.593, 0.0], [0.79, 0.773], [0.671, 0.889], [0.79, 0.0], [0.593, 0.296], [0.593, 0.593], [0.395, 0.593], [0.0, 0.889], [0.0, 0.0]]
FV = [[0, 5, 4, 1], [1, 9, 0], [8, 7, 0, 9], [7, 8, 3, 2, 4, 5, 6]]
EV = [[0, 1], [8, 9], [6, 7], [4, 5], [1, 4], [3, 8], [5, 6], [2, 3], [1, 9], [0, 9], [0, 5], [0, 7], [7, 8], [2, 4]]
polylines = [[V[v] for v in face+[face[0]]] for face in FV]
VIEW(EXPLODE(1.1,1.1,1)(MKPOLS((V,EV)) + AA(MK)(V) + AA(FAN)(polylines) ))

VV = AA(LIST)(range(len(V)))
submodel = STRUCT(MKPOLS((V,EV)))
VIEW(larModelNumbering(1,1,1)(V,[VV,EV,FV],submodel,.6))

VIEW(EXPLODE(1.1,1.1,1)(AA(POLYLINE)(polylines)))
@}
%-------------------------------------------------------------------------------

\appendix
%===============================================================================
\section{Code utilities}
%===============================================================================

\paragraph{Coding utilities}

Some utility fuctions used by the module are collected in this appendix. Their macro names can be seen in the below script.

%-------------------------------------------------------------------------------
@D Coding utilities
@{""" Coding utilities """
@< Generation of all binary subsets of lenght n @>
@< Generation of a random point @>
@< Generation of a random line segment @>
@< Transformation of a 2D box into a closed polyline @>
@< Computation of the 1D centroid of a list of 2D boxes @>
@< Pyplasm XOR of FAN of ordered points @>
@}
%-------------------------------------------------------------------------------

\paragraph{Generation of all binary subsets of lenght n}

%-------------------------------------------------------------------------------
@D Generation of all binary subsets of lenght n
@{""" Generation of all binary subsets of lenght n """
def allBinarySubsetsOfLenght(n):
	out = [list(('{0:0'+str(n)+'b}').format(k)) for k in range(1,2**n)]
	return AA(AA(int))(out)
@}
%-------------------------------------------------------------------------------

\subparagraph{Example}
\begin{verbatim}
In [9]: allBinarySubsetsOfLenght(3)
Out[9]: [[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
\end{verbatim}

\paragraph{Generation of random lines}
The function \texttt{randomLines} returns the array \texttt{randomLineArray} with a given number of lines generated within the unit 2D interval. The \texttt{scaling} parameter is used to scale every such line, generated by two randow points, that could be possibly located to far from each other, even at the distance of the diagonal of the unit square.

The arrays \texttt{xs} and \texttt{ys}, that contain the $x$ and $y$ coordinates of line points, are used to compute the minimal translation \texttt{v} needed to transport the entire set of data within the positive quadrant of the 2D plane.

%-------------------------------------------------------------------------------
@D Generation of random lines
@{""" Generation of random lines """
def randomLines(numberOfLines=200,scaling=0.3):
    randomLineArray = [redge(scaling) for k in range(numberOfLines)]
    [xs,ys] = TRANS(CAT(randomLineArray))[:2]
    xmin, ymin = min(xs), min(ys)
    v = array([-xmin,-ymin])
    randomLineArray = [[list(v1[:2]+v), list(v2[:2]+v)] for v1,v2 in randomLineArray]
    return randomLineArray
@}
%-------------------------------------------------------------------------------

\paragraph{Generation of a random point}
A single random point, codified in floating point format, and with a fixed (quite small) number of digits, is returned by the \texttt{rpoint2d()} function, with no input parameters.
%-------------------------------------------------------------------------------
@D Generation of a random point
@{""" Generation of a random point """
def rpoint2d():
    return eval( vcode(4)([ random.random(), random.random() ]) )
@}
%-------------------------------------------------------------------------------

\paragraph{Generation of a random line segment}
A single random segment, scaled about its centroid by the \texttt{scaling} parameter, is returned by the \texttt{redge()} function, as a tuple ot two random points in the unit square.
%-------------------------------------------------------------------------------
@D Generation of a random line segment
@{""" Generation of a random line segment """
def redge(scaling):
    v1,v2 = array(rpoint2d()), array(rpoint2d())
    c = (v1+v2)/2
    pos = rpoint2d()
    v1 = (v1-c)*scaling + pos
    v2 = (v2-c)*scaling + pos
    return tuple(eval(vcode(4)(v1))), tuple(eval(vcode(4)(v2)))
@}
%-------------------------------------------------------------------------------

\paragraph{Transformation of a 2D box into a closed polyline}
The transformation of a 2D box into a closed rectangular polyline, given as an ordered sequwncw of 2D points, is produced by the function \texttt{box2rect}
%-------------------------------------------------------------------------------
@D Transformation of a 2D box into a closed polyline
@{""" Transformation of a 2D box into a closed polyline """
def box2rect(box):
    x1,y1,x2,y2 = box
    verts = [[x1,y1],[x2,y1],[x2,y2],[x1,y2],[x1,y1]]
    return verts
@}
%-------------------------------------------------------------------------------

\paragraph{Computation of the 1D centroid of a list of 2D boxes}
The 1D \texttt{centroid} of a list of 2D boxes is computed by the function given below.
The direction of computation (either $x$ or $y$) is chosen depending on the value of the \texttt{xy} parameter.
%-------------------------------------------------------------------------------
@D Computation of the 1D centroid of a list of 2D boxes
@{""" Computation of the 1D centroid of a list of 2D boxes """
def centroid(boxes,coord):
    delta,n = 0,len(boxes)
    ncoords = len(boxes[0])/2
    a = coord%ncoords
    b = a+ncoords
    for box in boxes:
        delta += (box[a] + box[b])/2
    return delta/n

@}
%-------------------------------------------------------------------------------

\paragraph{Pyplasm XOR of FAN of ordered points}

%-------------------------------------------------------------------------------
@D Pyplasm XOR of FAN of ordered points
@{""" XOR of FAN of ordered points """
def FAN(points):
    pairs = zip(points[1:-2],points[2:-1])
    triangles = [MKPOL([[points[0],p1,p2],[[1,2,3]],None]) for p1,p2 in pairs]
    return XOR(triangles)

if __name__=="__main__":
    pol = [[0.476,0.332],[0.461,0.359],[0.491,0.375],[0.512,0.375],[0.514,0.375],
    [0.527,0.375],[0.543,0.34],[0.551,0.321],[0.605,0.314],[0.602,0.307],[0.589,
    0.279],[0.565,0.244],[0.559,0.235],[0.553,0.227],[0.527,0.239],[0.476,0.332]]

    VIEW(EXPLODE(1.2,1.2,1)(FAN(pol)))
@}
%-------------------------------------------------------------------------------

\bibliographystyle{amsalpha}
\bibliography{inters}

\end{document}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LaTeX Example: Project Report
%
% Source: http://www.howtotex.com
%
% Feel free to distribute this example, but please keep the referral
% to howtotex.com
% Date: March 2011
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% How to use writeLaTeX:
%
% You edit the source code here on the left, and the preview on the
% right shows you the result within a few seconds.
%
% Bookmark this page and share the URL with your co-authors. They can
% edit at the same time!
%
% You can upload figures, bibliographies, custom classes and
% styles using the files menu.
%
% If you're new to LaTeX, the wikibook is a great place to start:
% http://en.wikibooks.org/wiki/LaTeX
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Edit the title below to update the display in My Documents
%\title{Project Report}
%
%%% Preamble
\documentclass[paper=a4, fontsize=11pt]{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{fourier}

\usepackage[english]{babel}															% English language/hyphenation
\usepackage[protrusion=true,expansion=true]{microtype}
\usepackage{amsmath,amsfonts,amsthm} % Math packages
\usepackage[pdftex]{graphicx}
\usepackage{url}
\usepackage{caption}
\usepackage[top=1in, bottom=1in, left=1in, right=1in]{geometry}
\usepackage{subcaption}  % For placing two subfigures side by side

%%% Custom sectioning
\usepackage{sectsty}
\usepackage{multirow}
\allsectionsfont{\centering \normalfont\scshape}

%%% Inserting landscape pages
\usepackage{pdflscape}

%%% Custom headers/footers (fancyhdr package)
\usepackage{fancyhdr}
\pagestyle{fancyplain}
\fancyhead{}											% No page header
\fancyfoot[L]{}											% Empty
\fancyfoot[C]{}											% Empty
\fancyfoot[R]{\thepage}									% Pagenumbering
\renewcommand{\headrulewidth}{0pt}			% Remove header underlines
\renewcommand{\footrulewidth}{0pt}				% Remove footer underlines
\setlength{\headheight}{13.6pt}
\setlength{\fboxrule}{1mm}
\setlength{\fboxsep}{5mm}

%%% Equation and float numbering
\numberwithin{equation}{section}		% Equationnumbering: section.eq#
\numberwithin{figure}{section}			% Figurenumbering: section.fig#
\numberwithin{table}{section}				% Tablenumbering: section.tab#

%%% Maketitle metadata
\newcommand{\horrule}[1]{\rule{\linewidth}{#1}} 	% Horizontal rule

\title{
		%\vspace{-1in}
		\usefont{OT1}{bch}{b}{n}
		\horrule{0.5pt} \\[0.2cm]
		\LARGE Deriving an analytical expression for the local extrema of a bivariate B-spline of degree 2\\
        -\\
        \normalsize Another tool for characterising sawtooth crash precursors
		\horrule{2pt} \\[0.3cm]
}
\author{D. VEZINET}
\date{\today}

% Graphics path
\graphicspath{ {./} }

%%% Begin document
\begin{document}
\maketitle

\tableofcontents

\newpage
\section{General expression of the surface and gradient}

\begin{figure}[hbtp]
    \centering
    \includegraphics[scale=0.35]{Fig_Grid.png}
    \caption{\small Grid element on which we want to check the existence of a point of null gradient}
    \label{Fig:Grid}
\end{figure}

On the mesh element illustrated in \ref{Fig:Grid} (disregarding boundary effects, i.e.: assuming no basis function is missing) a bivariate B-spline of degree 2 can be written:
$$
\begin{array}{ll}
F(x,y) &= \sum_{i=0}^{9}C_{i}F_i(x,y)\\
&=
\begin{array}{ll}
& C_{00}f_{x0..3}(x)f_{y0..3}(y) + C_{01}f_{x1..4}(x)f_{y0..3}(y) + C_{02}f_{x2..5}(x)f_{y0..3}(y)\\
+& C_{10}f_{x0..3}(x)f_{y1..4}(y) + C_{11}f_{x1..4}(x)f_{y1..4}(y) + C_{12}f_{x2..5}(x)f_{y1..4}(y)\\
+& C_{20}f_{x0..3}(x)f_{y2..5}(y) + C_{21}f_{x1..4}(x)f_{y2..5}(y) + C_{22}f_{x2..5}(x)f_{y2..5}(y)
\end{array}
\end{array}
$$

Where $f_{x0..3} =
\left\{
\begin{array}{lll}
\frac{(x-x0)^2}{(x2-x0)(x1-x0)} & \text{ ,  if  } & x \in [x0,x1]\\
\frac{(x-x0)(x2-x)}{(x2-x0)(x2-x1)} + \frac{(x-x1)(x3-x)}{(x2-x1)(x3-x1)} & \text{ ,  if  } & x \in [x1,x2]\\
\frac{(x3-x)^2}{(x3-x2)(x3-x1)} & \text{ ,  if  } & x \in [x2,x3]
\end{array}
\right.
$

So $\frac{\partial f_{x0..3}}{\partial x} =
\left\{
\begin{array}{lll}
\frac{2(x-x0)}{(x2-x0)(x1-x0)} & \text{ ,  if  } & x \in [x0,x1]\\
\frac{-2x+(x0+x2)}{(x2-x0)(x2-x1)} + \frac{-2x+(x1+x3)}{(x2-x1)(x3-x1)} & \text{ ,  if  } & x \in [x1,x2]\\
\frac{-2(x3-x)}{(x3-x2)(x3-x1)} & \text{ ,  if  } & x \in [x2,x3]
\end{array}
\right.
$

We want to know for which points inside the mesh element of interest (i.e. $(x,y) \in [a2,a3]\times[b2,b3]$) we have:
$$
\begin{array}{ccc}
\underline{\nabla}F = 0 &\Leftrightarrow &
\left \{
\begin{array}{llc}
\sum_{i=0}^9 C_i f_{y...}(y)\frac{\partial f_{x...}}{\partial x}(x) = 0 & (1)\\
\sum_{i=0}^9 C_i f_{x...}(x)\frac{\partial f_{y...}}{\partial y}(y) = 0 & (2)
\end{array}
\right.
\end{array}
$$

We will treat case (1) in the following and deduce the similar expression for case (2).

%\frac{(x-x0)^2}{(x2-x0)(x1-x0)}

\newpage
\begin{landscape}
\section{Calculations}

\paragraph{\textbf{Trivial case}} If all $C_i$ are zero then the gradient is zero everywhere on the mesh element.

\paragraph{\textbf{Non-trivial case for (1)}} ... and assuming that all the knots are different
$$
\begin{array}{lll}
0 & = & \frac{(y3-y)^2}{(y3-y2)(y3-y1)} \left( C_{00}\frac{-2(x3-x)}{(x3-x2)(x3-x1)} + C_{01}\left( \frac{-2x+(x1+x3)}{(x3-x1)(x3-x2)} + \frac{-2x+(x2+x4)}{(x3-x2)(x4-x2)} \right) + C_{02}\frac{2(x-x2)}{(x4-x2)(x3-x2)}  \right)\\
& & + \left( \frac{(y-y1)(y3-y)}{(y3-y1)(y3-y2)} + \frac{(y-y2)(y4-y)}{(y3-y2)(y4-y2)} \right) \left( C_{10}\frac{-2(x3-x)}{(x3-x2)(x3-x1)} + C_{11}\left( \frac{-2x+(x1+x3)}{(x3-x1)(x3-x2)} + \frac{-2x+(x2+x4)}{(x3-x2)(x4-x2)} \right) + C_{12}\frac{2(x-x2)}{(x4-x2)(x3-x2)} \right)\\
& & + \frac{(y-y2)^2}{(y4-y2)(y3-y2)} \left( C_{20}\frac{-2(x3-x)}{(x3-x2)(x3-x1)} + C_{21}\left( \frac{-2x+(x1+x3)}{(x3-x1)(x3-x2)} + \frac{-2x+(x2+x4)}{(x3-x2)(x4-x2)} \right) + C_{22}\frac{2(x-x2)}{(x4-x2)(x3-x2)} \right)\\

& = & \frac{(y3-y)^2}{(y3-y1)} \left( C_{00}\frac{-2(x3-x)}{(x3-x1)} + C_{01}\left( \frac{-2x+(x1+x3)}{(x3-x1)} + \frac{-2x+(x2+x4)}{(x4-x2)} \right) + C_{02}\frac{2(x-x2)}{(x4-x2)}  \right)\\
& & + \left( \frac{(y-y1)(y3-y)}{(y3-y1)} + \frac{(y-y2)(y4-y)}{(y4-y2)} \right) \left( C_{10}\frac{-2(x3-x)}{(x3-x1)} + C_{11}\left( \frac{-2x+(x1+x3)}{(x3-x1)} + \frac{-2x+(x2+x4)}{(x4-x2)} \right) + C_{12}\frac{2(x-x2)}{(x4-x2)} \right)\\
& & + \frac{(y-y2)^2}{(y4-y2)} \left( C_{20}\frac{-2(x3-x)}{(x3-x1)} + C_{21}\left( \frac{-2x+(x1+x3)}{(x3-x1)} + \frac{-2x+(x2+x4)}{(x4-x2)} \right) + C_{22}\frac{2(x-x2)}{(x4-x2)} \right)\\

& = & \frac{(y3-y)^2}{(y3-y1)} \left( x\left( \frac{2C_{00}}{(x3-x1)} + \frac{-2C_{01}}{(x3-x1)} + \frac{-2C_{01}}{(x4-x2)} + \frac{2C_{02}}{(x4-x2)} \right) +  \frac{-2x3C_{00}}{(x3-x1)} + \frac{C_{01}(x1+x3)}{(x3-x1)} + \frac{C_{01}(x2+x4)}{(x4-x2)} + \frac{-2x2C_{02}}{(x4-x2)} \right)\\
& & + \left( \frac{(y-y1)(y3-y)}{(y3-y1)} + \frac{(y-y2)(y4-y)}{(y4-y2)} \right) \left( x\left( \frac{2C_{10}}{(x3-x1)} + \frac{-2C_{11}}{(x3-x1)} + \frac{-2C_{11}}{(x4-x2)} + \frac{2C_{12}}{(x4-x2)} \right) +  \frac{-2x3C_{10}}{(x3-x1)} + \frac{C_{11}(x1+x3)}{(x3-x1)} + \frac{C_{11}(x2+x4)}{(x4-x2)} + \frac{-2x2C_{12}}{(x4-x2)} \right)\\
& & + \frac{(y-y2)^2}{(y4-y2)} \left( x\left( \frac{2C_{20}}{(x3-x1)} + \frac{-2C_{21}}{(x3-x1)} + \frac{-2C_{21}}{(x4-x2)} + \frac{2C_{22}}{(x4-x2)} \right) +  \frac{-2x3C_{20}}{(x3-x1)} + \frac{C_{21}(x1+x3)}{(x3-x1)} + \frac{C_{21}(x2+x4)}{(x4-x2)} + \frac{-2x2C_{22}}{(x4-x2)} \right)
\end{array}
$$

So, by introducing $\left \{ \begin{array}{l} A_{x,i} = \frac{2(C_{i0}-C_{i1})}{(x3-x1)} + \frac{2(C_{i2}-C_{i1})}{(x4-x2)}\\ B_{x,i} = \frac{C_{i1}(x1+x3)-2x3C_{i0}}{(x3-x1)} + \frac{C_{i1}(x2+x4)-2x2C_{i2}}{(x4-x2)} \end{array} \right.$, we can write:
$$
\begin{array}{lll}
0 & = & \frac{(y3-y)^2}{(y3-y1)} \left( xA_{x,0} + B_{x,0} \right) + \left( \frac{(y-y1)(y3-y)}{(y3-y1)} + \frac{(y-y2)(y4-y)}{(y4-y2)} \right) \left( xA_{x,1} + B_{x,1} \right) + \frac{(y-y2)^2}{(y4-y2)} \left( xA_{x,2} + B_{x,2} \right)\\
& = & y^2 \left( \frac{xA_{x,0} + B_{x,0}}{y3-y1} - \frac{xA_{x,1} + B_{x,1}}{y3-y1} - \frac{xA_{x,1} + B_{x,1}}{y4-y2} + \frac{xA_{x,2} + B_{x,2}}{y4-y2} \right)\\
& & + y\left( -2y3\frac{xA_{x,0} + B_{x,0}}{y3-y1} + \frac{y3+y1}{y3-y1}\left( xA_{x,1} + B_{x,1} \right) + \frac{y4+y2}{y4-y2}\left( xA_{x,1} + B_{x,1} \right) - 2y2\frac{xA_{x,2} + B_{x,2}}{y4-y2} \right)\\
& & + y3^2\frac{xA_{x,0} + B_{x,0}}{y3-y1} - y3y1\frac{xA_{x,1} + B_{x,1}}{y3-y1} - y4y2\frac{xA_{x,1} + B_{x,1}}{y4-y2} + y2^2\frac{xA_{x,2} + B_{x,2}}{y4-y2}\\

& = & y^2 \left( \frac{x\left(A_{x,0}-A_{x,1}\right) + B_{x,0}-B_{x,1}}{y3-y1} + \frac{x\left(A_{x,2}-A_{x,1}\right) + B_{x,2}-B_{x,1}}{y4-y2} \right)\\
& & + y\left( \frac{(y3+y1)\left( xA_{x,1} + B_{x,1} \right) - 2y3\left(xA_{x,0} + B_{x,0}\right)}{y3-y1} + \frac{(y4+y2)\left( xA_{x,1} + B_{x,1} \right) - 2y2\left(xA_{x,2} + B_{x,2}\right)}{y4-y2} \right)\\
& & + \frac{y3^2\left(xA_{x,0} + B_{x,0}\right) - y3y1\left(xA_{x,1} + B_{x,1}\right)}{y3-y1} + \frac{y2^2\left(xA_{x,2} + B_{x,2}\right) - y4y2\left(xA_{x,1} + B_{x,1}\right)}{y4-y2}
\end{array}
$$

\end{landscape}

\newpage
\section{Overview of the reduced set of equations}
Hence, we can write that a point with gradient zero will have:
$$
\left \{
\begin{array}{l}
y^2 P_2(x) + yP_1(x) + P_0(x) = 0\\
x^2 Q_2(y) + xQ_1(y) + Q_0(y) = 0
\end{array}
\right.
$$

Where:
$$
\left \{
\begin{array}{ll}
P_2(x) = x\left( \frac{A_{x,0}-A_{x,1}}{y3-y1} + \frac{A_{x,2}-A_{x,1}}{y4-y2} \right) + \frac{B_{x,0}-B_{x,1}}{y3-y1} + \frac{B_{x,2}-B_{x,1}}{y4-y2}  & = xa_{P2} + b_{P2}\\
P_1(x) = x\left( \frac{(y3+y1)A_{x,1} - 2y3A_{x,0}}{y3-y1} + \frac{(y4+y2)A_{x,1} - 2y2A_{x,2}}{y4-y2} \right) + \frac{(y3+y1)B_{x,1} - 2y3B_{x,0}}{y3-y1} + \frac{(y4+y2)B_{x,1} - 2y2B_{x,2}}{y4-y2}  & = xa_{P1} + b_{P1}\\
P_0(x) = x\left( \frac{y3^2A_{x,0} - y3y1xA_{x,1}}{y3-y1} + \frac{y2^2A_{x,2} - y4y2A_{x,1}}{y4-y2} \right) + \frac{y3^2B_{x,0} - y3y1xB_{x,1}}{y3-y1} + \frac{y2^2B_{x,2} - y4y2B_{x,1}}{y4-y2}  & = xa_{P0} + b_{P0}
\end{array}
\right.
$$

And:
$$
\left \{
\begin{array}{ll}
Q_2(y) = y\left( \frac{A_{y,0}-A_{y,1}}{x3-x1} + \frac{A_{y,2}-A_{y,1}}{x4-x2} \right) + \frac{B_{y,0}-B_{y,1}}{x3-x1} + \frac{B_{y,2}-B_{y,1}}{x4-x2}  & = ya_{Q2} + b_{Q2}\\
Q_1(y) = y\left( \frac{(x3+x1)A_{y,1} - 2x3A_{y,0}}{x3-x1} + \frac{(x4+x2)A_{y,1} - 2x2A_{y,2}}{x4-x2} \right) + \frac{(x3+x1)B_{y,1} - 2x3B_{y,0}}{x3-x1} + \frac{(x4+x2)B_{y,1} - 2x2B_{y,2}}{x4-x2}  & = ya_{Q1} + b_{Q1}\\
Q_0(y) = y\left( \frac{x3^2A_{y,0} - x3x1xA_{y,1}}{x3-x1} + \frac{x2^2A_{y,2} - x4x2A_{y,1}}{x4-x2} \right) + \frac{x3^2B_{y,0} - x3x1xB_{y,1}}{x3-x1} + \frac{x2^2B_{y,2} - x4x2B_{y,1}}{x4-x2}  & = ya_{Q0} + b_{Q0}
\end{array}
\right.
$$

In the following, we will explore the various cases of this set of equations, keeping in mind that we are looking for a solution in $[x2,x3]\times[y2,y3]$

\newpage
\section{Cases of the reduced set of equations}

\subsection{$P_2(x) = 0$}

Necessarily, if $P_2(x)=0$ then:
$$
x\left( \frac{A_{x,0}-A_{x,1}}{y3-y1} + \frac{A_{x,2}-A_{x,1}}{y4-y2} \right) = -\frac{B_{x,0}-B_{x,1}}{y3-y1} + \frac{B_{x,2}-B_{x,1}}{y4-y2}\\
$$

\paragraph{\textbf{Case 01}} $\frac{A_{x,0}-A_{x,1}}{y3-y1} + \frac{A_{x,2}-A_{x,1}}{y4-y2} = 0$\\
%Then $\frac{2}{y3-y1}\left( \frac{(C_{00}-C_{01})}{(x3-x1)} + \frac{(C_{02}-C_{01})}{(x4-x2)} - \frac{(C_{10}-C_{11})}{(x3-x1)} + \frac{(C_{12}-C_{11})}{(x4-x2)} \right)
%+ \frac{2}{y4-y2}\left( \frac{(C_{20}-C_{21})}{(x3-x1)} + \frac{(C_{22}-C_{21})}{(x4-x2)} - \frac{(C_{10}-C_{11})}{(x3-x1)} + \frac{(C_{12}-C_{11})}{(x4-x2)} \right) = 0$
Then:
\begin{enumerate}
\item If $\frac{B_{x,0}-B_{x,1}}{y3-y1} + \frac{B_{x,2}-B_{x,1}}{y4-y2} \neq 0$, no possible solution
\item If $\frac{B_{x,0}-B_{x,1}}{y3-y1} + \frac{B_{x,2}-B_{x,1}}{y4-y2} = 0$, all x are solution
\end{enumerate}

Thus, some solutions are accessible in $[x2,x3]\times[y2,y3]$ in the second case.

\paragraph{\textbf{Case 02}} $\frac{A_{x,0}-A_{x,1}}{y3-y1} + \frac{A_{x,2}-A_{x,1}}{y4-y2} \neq 0$\\
Then $x_0 = -\frac{\frac{B_{x,0}-B_{x,1}}{y3-y1} + \frac{B_{x,2}-B_{x,1}}{y4-y2}}{\frac{A_{x,0}-A_{x,1}}{y3-y1} + \frac{A_{x,2}-A_{x,1}}{y4-y2}}$\\
Thus, a solutions is accessible in $[x2,x3]\times[y2,y3]$ only if $x_0 \in [x2,x3]\times[y2,y3]$.\\

\paragraph{\textbf{Consequences}}

Let $P_2(x_0)=0$ with $x_0 \in [x2,x3]$, then:
$$
\left \{
\begin{array}{ll}
yP_1(x_0) + P_0(x_0) = 0 & (1)\\
x_0^2 Q_2(y) + x_0Q_1(y) + Q_0(y) = 0 & (2)
\end{array}
\right.
$$

\begin{enumerate}
\item if $P_1(x_0)=0$ and $P_0(x_0)\neq0$, no solution
\item if $P_1(x_0)=0$ and $P_0(x_0)=0$, eq.$(1)$ gives no constraint on y
\item if $P_1(x_0)\neq0$ then $y_0 = -\frac{P_0(x_0)}{P_1(x_0)}$, then sol = $(x_0,y_0)$ if $\left\{\begin{array}{l}(x_0,y_0) \in [x2,x3]\times[y2,y3]\\x_0^2 Q_2(y_0) + x_0Q_1(y_0) + Q_0(y_0) = 0 \end{array}\right.$
\end{enumerate}

In case 2, we have to use eq. $(2)$ to get a value for y, which will give the same three possibilities (it is a degree 1 polynomial in y):
\begin{enumerate}
\item No solution if the coef. of y is zero but the rest is non-zero
\item All y are solution if the coef. of y is zero and the rest is zero too
\item There exist a unique solution $y_0 = -rest/coef.$, check whether it lies in $[y2,y3]$
\end{enumerate}

\newpage
\subsection{$Q_2(y) = 0$}

Similarly to the previous case, $Q_2(y) = 0$ is only possible if:
\begin{enumerate}
\item If $\frac{B_{y,0}-B_{y,1}}{x3-x1} + \frac{B_{y,2}-B_{y,1}}{x4-x2} \neq 0$, no possible solution
\item If $\frac{B_{y,0}-B_{y,1}}{x3-x1} + \frac{B_{y,2}-B_{y,1}}{x4-x2} = 0$, all y are solution
\item Otherwise $y_0 = -\frac{\frac{B_{y,0}-B_{y,1}}{x3-x1} + \frac{B_{y,2}-B_{y,1}}{x4-x2}}{\frac{A_{y,0}-A_{y,1}}{x3-x1} + \frac{A_{y,2}-A_{y,1}}{x4-x2}}$ is the unique solution
\end{enumerate}

And if there is a solution $y_0 \in [y2,y3]$, then:
\begin{enumerate}
\item if $Q_1(y_0)=0$ and $Q_0(y_0)\neq0$, no solution
\item if $Q_1(y_0)=0$ and $Q_0(y_0)=0$, eq.$(2)$ gives no constraint on x
\item if $Q_1(y_0)\neq0$ then $x_0 = -\frac{Q_0(y_0)}{Q_1(y_0)}$, then sol = $(x_0,y_0)$ if $\left\{\begin{array}{l}(x_0,y_0) \in [x2,x3]\times[y2,y3]\\y_0^2 P_2(x_0) + y_0P_1(x_0) + P_0(x_0) = 0 \end{array}\right.$
\end{enumerate}

In case 2, we have to use eq. $(1)$ to get a value for x, which will give the same three possibilities (it is a degree 1 polynomial in y):
\begin{enumerate}
\item No solution if the coef. of x is zero but the rest is non-zero
\item All y are solution if the coef. of x is zero and the rest is zero too
\item There exist a unique solution $x_0 = -rest/coef.$, check whether it lies in $[x2,x3]$
\end{enumerate}

\newpage
\subsection{$P_2(x)\neq0 \text{ and } Q_2(y)\neq0$}

In this general case, we have to check the existence of solutions to two degree 2 polynomials:
$$
\begin{array}{ll}
& \left \{
\begin{array}{ll}
\Delta_y(x) = P_1^2(x) - 4P_2^2(x)P_0^2(x) \geq 0 & (1)\\
\Delta_x(y) = Q_1^2(y) - 4Q_2^2(y)Q_0^2(y) \geq 0 & (2)
\end{array}
\right.\\
\Leftrightarrow & \left \{
\begin{array}{ll}
x^2 \left( a_{P1}^2-4a_{P2}a_{P0} \right) + x\left( 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} \right) + b_{P1}^2-4b_{P2}b_{P0} \geq 0 & (1)\\
y^2 \left( a_{Q1}^2-4a_{Q2}a_{Q0} \right) + y\left( 2a_{Q1}b_{Q1} - 4a_{Q2}b_{Q0} - 4a_{Q0}b_{Q2} \right) + b_{Q1}^2-4b_{Q2}b_{Q0} \geq 0 & (2)
\end{array}
\right.
\end{array}
$$

Which means, by defining $\left\{\begin{array}{l}\delta_x = \left( 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} \right)^2-4\left( a_{P1}^2-4a_{P2}a_{P0} \right)\left(b_{P1}^2-4b_{P2}b_{P0}\right)\\
\delta_y = \left( 2a_{Q1}b_{Q1} - 4a_{Q2}b_{Q0} - 4a_{Q0}b_{Q2} \right)^2-4\left( a_{Q1}^2-4a_{Q2}a_{Q0} \right)\left(b_{Q1}^2-4b_{Q2}b_{Q0}\right)\end{array}\right.$:
\begin{enumerate}
\item If $\left\{\begin{array}{l}a_{P1}^2-4a_{P2}a_{P0}=0\\ 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} > 0\end{array}\right.$ then $x \in [x_0,\infty]\cap[x2,x3]$, with $x_0=-\frac{b_{P1}^2-4b_{P2}b_{P0}}{2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2}}$
\item If $\left\{\begin{array}{l}a_{P1}^2-4a_{P2}a_{P0}=0\\ 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} < 0\end{array}\right.$ then $x \in [-\infty,x_0]\cap[x2,x3]$, with $x_0=-\frac{b_{P1}^2-4b_{P2}b_{P0}}{2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2}}$
\item If $\left\{\begin{array}{l}a_{P1}^2-4a_{P2}a_{P0}=0\\ 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} = 0\end{array}\right.$ then $\left\{\begin{array}{l}b_{P1}^2-4b_{P2}b_{P0}=0 \Rightarrow \text{ all x solutions}\\ b_{P1}^2-4b_{P2}b_{P0} \neq 0 \Rightarrow \text{ no solution}\end{array}\right.$
\item If $\left\{\begin{array}{l}\delta_x < 0\\a_{P1}^2-4a_{P2}a_{P0} > 0 \end{array}\right.$, then all $x \in [x2,x3]$ are solution
\item If $\left\{\begin{array}{l}\delta_x < 0\\a_{P1}^2-4a_{P2}a_{P0} < 0 \end{array}\right.$, then no solution
\item If $\left\{\begin{array}{l}\delta_x \geq 0\\a_{P1}^2-4a_{P2}a_{P0} > 0 \end{array}\right.$, then $x \in \left([-\infty,x_1] \cup [x_2,\infty]\right) \cap [x2,x3]$ with $x_{1,2}=\frac{-\left( 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} \right) \pm \sqrt{\delta_x}}{2\left( a_{P1}^2-4a_{P2}a_{P0} \right)}$
\item If $\left\{\begin{array}{l}\delta_x \geq 0\\a_{P1}^2-4a_{P2}a_{P0} < 0 \end{array}\right.$, then $x \in [x_1,x_2] \cap [x2,x3]$ with $x_{1,2}=\frac{-\left( 2a_{P1}b_{P1} - 4a_{P2}b_{P0} - 4a_{P0}b_{P2} \right) \pm \sqrt{\delta_x}}{2\left( a_{P1}^2-4a_{P2}a_{P0} \right)}$
\end{enumerate}

And idem for y

\newpage
\begin{landscape}
\paragraph{\textbf{Consequences}} Now let $I_x = [x_1,x_2] \subset [x2,x3]$ and $I_y = [y_1,y_2] \subset [y2,y3]$ be the two intervals satisfying $\Delta_y(x)\geq0$ and $\Delta_x(y)\geq0$, then:
$$
\begin{array}{ll}
&
\left \{
\begin{array}{l}
y = \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)}\\
x = \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)}
\end{array}
\right.\\
\Leftrightarrow &
\left \{
\begin{array}{l}
2yP_2\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right) = -P_1\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right) \pm \sqrt{\Delta_y\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right)}\\
2xQ_2\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right) = -Q_1\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right) \pm \sqrt{\Delta_x\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right)}
\end{array}
\right.\\
\Leftrightarrow &
\left \{
\begin{array}{l}
2y\left( a_{P2}\left( -Q_1(y) \pm \sqrt{\Delta_x(y)} \right) + 2Q_2(y)b_{P2} \right) = -\left( a_{P1} \left(-Q_1(y) \pm \sqrt{\Delta_x(y)} \right) + 2Q_2(y)b_{P1} \right) \pm 2Q_2(y)\sqrt{\Delta_y\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right)}\\
2x\left( a_{Q2}\left(-P_1(x) \pm \sqrt{\Delta_y(x)} \right) + 2P_2(x)b_{Q2} \right) = -\left( a_{Q1} \left(-P_1(x) \pm \sqrt{\Delta_y(x)} \right) + 2P_2(x)b_{Q1} \right) \pm 2P_2(x)\sqrt{\Delta_x\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right)}
\end{array}
\right.\\
\Leftrightarrow &
\left \{
\begin{array}{l}
2y\left( a_{P2}\left( -a_{Q1}y - b_{Q1} \pm \sqrt{\Delta_x(y)} \right) + 2b_{P2}\left(a_{Q2}y+b_{Q2}\right) \right) = -\left( a_{P1} \left(-a_{Q1}y - b_{Q1} \pm \sqrt{\Delta_x(y)} \right) + 2b_{P1}\left( a_{Q2}y+b_{Q2}\right) \right) \pm 2Q_2(y)\sqrt{\Delta_y\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right)}\\
2x\left( a_{Q2}\left(-a_{P1}x-b_{P1} \pm \sqrt{\Delta_y(x)} \right) + 2b_{Q2}\left(a_{P2}x+b_{P2}\right) \right) = -\left( a_{Q1} \left(-a_{P1}x-b_{P1} \pm \sqrt{\Delta_y(x)} \right) + 2b_{Q1}\left(a_{P2}x+b_{P2}\right) \right) \pm 2P_2(x)\sqrt{\Delta_x\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right)}
\end{array}
\right.\\
\Leftrightarrow &
\left \{
\begin{array}{l}
y^2 \left( -2a_{P2}a_{Q1}+4b_{P2}a_{Q2} \right) + y\left( -2a_{P2}b_{Q1}+2b_{P2}b_{Q2}-a_{P1}a_{Q1}+2b_{P1}a_{Q2} \pm 2a_{P2}\sqrt{\Delta_x(y)} \right) + \left( -a_{P1}b_{Q1} + 2b_{P1}b_{Q2} \pm a_{P1}\sqrt{\Delta_x(y)} \right) \mp 2Q_2(y)\sqrt{\Delta_y\left( \frac{-Q_1(y) \pm \sqrt{\Delta_x(y)}}{2Q_2(y)} \right)}\\
x^2 \left( -2a_{Q2}a_{P1}+4b_{Q2}a_{P2} \right) + x\left( -2a_{Q2}b_{P1}+2b_{Q2}b_{P2}-a_{Q1}a_{P1}+2b_{Q1}a_{P2} \pm 2a_{Q2}\sqrt{\Delta_y(x)} \right) + \left( -a_{Q1}b_{P1} + 2b_{Q1}b_{P2} \pm a_{Q1}\sqrt{\Delta_y(x)} \right) \mp 2P_2(x)\sqrt{\Delta_x\left( \frac{-P_1(x) \pm \sqrt{\Delta_y(x)}}{2P_2(x)} \right)}
\end{array}
\right.
\end{array}
$$

... And this is as far as I get analytically, any idea ? any reference ?

\end{landscape}

%%% End document
\end{document}