;File : path_cross_align.il
;Author : ZouJunlin
;Date : 2017/05/17
;Description: align perpendicular path groups with diagonal direction.
;step 1 : seperate paths to horizontal_paths and vertical_paths
;step 2 : sort paths group with ascend or descend order
;step 3 : conjunct each path from horizontal_paths and vertical_paths respectively
procedure(path_cross_align(crossType) ; crosstype == diagonal45 or diagonal135
let((cv objSet x allPaths horizontalPaths verticalPaths)
cv = geGetEditCellView()
bjSet = geGetSelectedSet()
; step 1 : seperate paths to horizontal_paths and vertical_paths
allPaths = setof(x objSet (x->objType == "path"))
foreach(x allPaths
if(pathDirection(x)=="horizontal" then horizontalPaths = append1(horizontalPaths x));end if
if(pathDirection(x)=="vertical" then verticalPaths = append1(verticalPaths x));end if
);end foreach
; step 2 : sort paths group with ascend or descend order
horizontalPaths = sortPathGroup(horizontalPaths "ascend")
if(crossType == "diagonal45" then verticalPaths = sortPathGroup(verticalPaths "ascend"));end if
if(crossType == "diagonal135" then verticalPaths = sortPathGroup(verticalPaths "descend"));end if
; step 3 : conjunct each path from horizontal_paths and vertical_paths respectively
mapcar('conjunctPerpendicularPath horizontalPaths verticalPaths)
);end let
);end procedure
procedure(pathDirection(path)
prog((point1 x1 y1 point2 x2 y2)
point1 = car(path->points)
x1 = car(point1)
y1 = cadr(point1)
point2 = cadr(path->points)
x2 = car(point2)
y2 = cadr(point2)
if(y1 == y2 then return("horizontal"));end if
if(x1 == x2 then return("vertical"));end if
if((x1-x2)*(y1-y2) > 0 then return("diagonal45"));end if
if((x1-x2)*(y1-y2) < 0 then return("diagonal135"));end if
);end prog
);end procedure
procedure(sortPathGroup(pathList mode)
prog((x pathDir tmpList sortedPathList)
x = nth(0 pathList)
pathDir = pathDirection(x)
;construct tmp_list with (y_coordinate path) for horizontalPaths
;construct tmp_list with (x_coordinate path) for verticalPaths
if(pathDir == "horizontal" then
foreach(x pathList
y_coordinate = cadar(x->points)
tmpList = append1(tmpList list(y_coordinate x))
);end foreach
);end if
if(pathDir == "vertical" then
foreach(x pathList
x_coordinate = caar(x->points)
tmpList = append1(tmpList list(x_coordinate x))
);end foreach
);end if
if(mode == "ascend" then tmpList = sortcar(tmpList 'lessp));end if
if(mode == "descend" then tmpList = sortcar(tmpList 'greaterp));end if
foreach(x tmpList sortedPathList = append1(sortedPathList cadr(x)));end foreach
return(sortedPathList)
);end prog
);end procedure
procedure(conjunctPerpendicularPath(hPath vPath)
let((leftPoint rightPoint bottomPoint topPoint crossPoint crossEndPoint width_h width_v)
leftPoint = car(hPath->points)
rightPoint = cadr(hPath->points)
bottomPoint = car(vPath->points)
topPoint = cadr(vPath->points)
crossPoint = list(car(topPoint) cadr(leftPoint))
width_h = hPath->width
width_v = vPath->width
if(orthogonalDistance(leftPoint crossPoint) > orthogonalDistance(rightPoint crossPoint) then
;adjust crossPoint to crossEndPoint before modify the target path
crossEndPoint = adjustEndPoint(leftPoint crossPoint "horizontal" width_v)
hPath->points = list(leftPoint crossEndPoint)
else
crossEndPoint = adjustEndPoint(rightPoint crossPoint "horizontal" width_v)
hPath->points = list(rightPoint crossEndPoint)
);end if
if(orthogonalDistance(bottomPoint crossPoint) > orthogonalDistance(topPoint crossPoint) then
;adjust crossPoint to crossEndPoint before modify the target path
crossEndPoint = adjustEndPoint(bottomPoint crossPoint "vertical" width_h)
vPath->points = list(bottomPoint crossEndPoint)
else
crossEndPoint = adjustEndPoint(topPoint crossPoint "vertical" width_h)
vPath->points = list(topPoint crossEndPoint)
);end if
);end let
);end procedure
procedure(orthogonalDistance(point1 point2)
prog((x1 y1 x2 y2)
x1 = car(point1)
y1 = cadr(point1)
x2 = car(point2)
y2 = cadr(point2)
return(abs(x1 - x2) + abs(y1 - y2)) ; always one of the result == 0
);end prog
);end procedure
procedure(adjustEndPoint(refPoint crossPoint pathDirection width)
prog((crossEndPoint)
if(pathDirection == "horizontal" then
if(car(refPoint) < car(crossPoint) then
crossEndPoint = list((car(crossPoint)+width/2) cadr(crossPoint))
else
crossEndPoint = list((car(crossPoint)-width/2) cadr(crossPoint))
);end if
);end if
if(pathDirection == "vertical" then
if(cadr(refPoint) < cadr(crossPoint) then
crossEndPoint = list(car(crossPoint) (cadr(crossPoint)+width/2) )
else
crossEndPoint = list(car(crossPoint) (cadr(crossPoint)-width/2) )
);end if
);end if
return(crossEndPoint)
);end prog
);end procedure
hiSetBindKey("
layout" "<Key>j" "path_cross_align(\"diagonal45\")")
hiSetBindKey("Layout" "shift<Key>j" "path_cross_align(\"diagonal135\")")