forked from bartvdbraak/blender
Added python func Blender.Geometry.LineIntersect2D(v1,v2,v3,v4)
updated archimap and cookie cutter to use it, removed python version from BPyMathutils archimap island merging is noticibly faster
This commit is contained in:
parent
dda63a9dde
commit
30d207e650
@ -182,86 +182,3 @@ def convexHull(point_list_2d):
|
||||
# Concatenate both halfs and return.
|
||||
return [p[1] for ls in (upper, lower) for p in ls]
|
||||
|
||||
SMALL_NUM = 0.000001
|
||||
def lineIntersect2D(v1a, v1b, v2a, v2b):
|
||||
'''
|
||||
Do 2 lines intersect, if so where.
|
||||
If there is an error, the retured X value will be None
|
||||
the y will be an error code- usefull when debugging.
|
||||
|
||||
the first line is (v1a, v1b)
|
||||
the second is (v2a, v2b)
|
||||
by Campbell Barton
|
||||
This function accounts for all known cases of 2 lines ;)
|
||||
'''
|
||||
|
||||
x1,y1= v1a.x, v1a.y
|
||||
x2,y2= v1b.x, v1b.y
|
||||
_x1,_y1= v2a.x, v2a.y
|
||||
_x2,_y2= v2b.x, v2b.y
|
||||
|
||||
# Bounding box intersection first.
|
||||
if min(x1, x2) > max(_x1, _x2) or \
|
||||
max(x1, x2) < min(_x1, _x2) or \
|
||||
min(y1, y2) > max(_y1, _y2) or \
|
||||
max(y1, y2) < min(_y1, _y2):
|
||||
return None, 100 # Basic Bounds intersection TEST returns false.
|
||||
|
||||
# are either of the segments points? Check Seg1
|
||||
if abs(x1 - x2) + abs(y1 - y2) <= SMALL_NUM:
|
||||
return None, 101
|
||||
|
||||
# are either of the segments points? Check Seg2
|
||||
if abs(_x1 - _x2) + abs(_y1 - _y2) <= SMALL_NUM:
|
||||
return None, 102
|
||||
|
||||
# Make sure the HOZ/Vert Line Comes first.
|
||||
if abs(_x1 - _x2) < SMALL_NUM or abs(_y1 - _y2) < SMALL_NUM:
|
||||
x1, x2, y1, y2, _x1, _x2, _y1, _y2 = _x1, _x2, _y1, _y2, x1, x2, y1, y2
|
||||
|
||||
if abs(x2-x1) < SMALL_NUM: # VERTICLE LINE
|
||||
if abs(_x2-_x1) < SMALL_NUM: # VERTICLE LINE SEG2
|
||||
return None, 111 # 2 verticle lines dont intersect.
|
||||
|
||||
elif abs(_y2-_y1) < SMALL_NUM:
|
||||
return x1, _y1 # X of vert, Y of hoz. no calculation.
|
||||
|
||||
yi = ((_y1 / abs(_x1 - _x2)) * abs(_x2 - x1)) + ((_y2 / abs(_x1 - _x2)) * abs(_x1 - x1))
|
||||
|
||||
if yi > max(y1, y2): # New point above seg1's vert line
|
||||
return None, 112
|
||||
elif yi < min(y1, y2): # New point below seg1's vert line
|
||||
return None, 113
|
||||
|
||||
return x1, yi # Intersecting.
|
||||
|
||||
|
||||
if abs(y2-y1) < SMALL_NUM: # HOZ LINE
|
||||
if abs(_y2-_y1) < SMALL_NUM: # HOZ LINE SEG2
|
||||
return None, 121 # 2 hoz lines dont intersect.
|
||||
|
||||
# Can skip vert line check for seg 2 since its covered above.
|
||||
xi = ((_x1 / abs(_y1 - _y2)) * abs(_y2 - y1)) + ((_x2 / abs(_y1 - _y2)) * abs(_y1 - y1))
|
||||
if xi > max(x1, x2): # New point right of seg1's hoz line
|
||||
return None, 112
|
||||
elif xi < min(x1, x2): # New point left of seg1's hoz line
|
||||
return None, 113
|
||||
|
||||
return xi, y1 # Intersecting.
|
||||
|
||||
# Accounted for hoz/vert lines. Go on with both anglular.
|
||||
b1 = (y2-y1)/(x2-x1)
|
||||
b2 = (_y2-_y1)/(_x2-_x1)
|
||||
a1 = y1-b1*x1
|
||||
a2 = _y1-b2*_x1
|
||||
|
||||
if b1 - b2 == 0.0:
|
||||
return None, 200
|
||||
|
||||
xi = - (a1-a2)/(b1-b2)
|
||||
yi = a1+b1*xi
|
||||
if (x1-xi)*(xi-x2) >= 0 and (_x1-xi)*(xi-_x2) >= 0 and (y1-yi)*(yi-y2) >= 0 and (_y1-yi)*(yi-_y2)>=0:
|
||||
return xi, yi
|
||||
else:
|
||||
return None, 300
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
import Blender
|
||||
Vector= Blender.Mathutils.Vector
|
||||
Ang= Blender.Mathutils.AngleBetweenVecs
|
||||
LineIntersect= Blender.Mathutils.LineIntersect
|
||||
CrossVecs= Blender.Mathutils.CrossVecs
|
||||
import BPyMesh
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Blender
|
||||
from Blender import Mathutils, Window, Scene, Draw, Mesh
|
||||
from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect, LineIntersect
|
||||
from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect
|
||||
|
||||
# DESCRIPTION:
|
||||
# screen_x, screen_y the origin point of the pick ray
|
||||
|
@ -119,6 +119,7 @@ def main():
|
||||
# -------------------------------
|
||||
|
||||
appstring = appstring.replace('%f', imageFileName)
|
||||
print '\tediting image with command "%s"' % appstring
|
||||
os.system(appstring)
|
||||
|
||||
if __name__ == '__main__' and os != None:
|
||||
|
@ -32,8 +32,8 @@ import Blender
|
||||
import BPyMathutils
|
||||
from math import sqrt
|
||||
reload(BPyMathutils)
|
||||
lineIntersect2D= BPyMathutils.lineIntersect2D
|
||||
Vector= Blender.Mathutils.Vector
|
||||
LineIntersect2D= Blender.Geometry.LineIntersect2D
|
||||
|
||||
# Auto class
|
||||
def auto_class(slots):
|
||||
@ -97,7 +97,7 @@ def point_in_poly2d(pt, fvco):
|
||||
#fvco= [v.co for v in face]
|
||||
isect=0
|
||||
for i in xrange(len(fvco)):
|
||||
isect+= (lineIntersect2D(pt, crazy_point, fvco[i], fvco[i-1])[0] != None)
|
||||
isect+= (LineIntersect2D(pt, crazy_point, fvco[i], fvco[i-1]) != None)
|
||||
|
||||
return isect%2 # odd number is an intersect which wouold be true (inside the face)
|
||||
|
||||
@ -289,11 +289,10 @@ def terrain_cut_2d(t, c, PREF_Z_LOC):
|
||||
if bounds_intersect(eb_t, eb_c): # face/edge bounds intersect?
|
||||
# Now we know the 2 edges might intersect, we'll do a propper test
|
||||
|
||||
xi, yi= lineIntersect2D(ed_t.v1.co, ed_t.v2.co, ed_c.v1.co, ed_c.v2.co)
|
||||
if xi != None:
|
||||
|
||||
x= LineIntersect2D(ed_t.v1.co, ed_t.v2.co, ed_c.v1.co, ed_c.v2.co)
|
||||
if x:
|
||||
ed_isect= edge_isect_type()
|
||||
ed_isect.point= Vector(xi,yi,0) # fake 3d
|
||||
ed_isect.point= x.resize3D() # fake 3d
|
||||
|
||||
# Find the interpolation Z point
|
||||
|
||||
@ -637,9 +636,7 @@ def main():
|
||||
if point_in_bounds(c, t.bounds):
|
||||
isect_count= 0
|
||||
for edv1, edv2 in edge_verts_c:
|
||||
xi, yi= lineIntersect2D(c, crazy_point, edv1, edv2)
|
||||
if xi!=None:
|
||||
isect_count+=1
|
||||
isect_count += (LineIntersect2D(c, crazy_point, edv1, edv2) != None)
|
||||
|
||||
if isect_count%2:
|
||||
f.sel= 1
|
||||
|
@ -42,7 +42,7 @@ selected faces, or all faces.
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
from Blender import Object, Scene, Draw, Window, sys, Mesh
|
||||
from Blender import Object, Scene, Draw, Window, sys, Mesh, Geometry
|
||||
from Blender.Mathutils import CrossVecs, Matrix, Vector, RotationMatrix, DotVecs, TriangleArea
|
||||
|
||||
from math import cos
|
||||
@ -262,7 +262,9 @@ def island2Edge(island):
|
||||
# If 2 are the same then they will be together, but full [a,b] order is not correct.
|
||||
|
||||
# Sort by length
|
||||
length_sorted_edges = [(key[0], key[1], value) for key, value in edges.iteritems() if value != 0]
|
||||
|
||||
|
||||
length_sorted_edges = [(Vector(key[0]), Vector(key[1]), value) for key, value in edges.iteritems() if value != 0]
|
||||
length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2]))
|
||||
|
||||
# Its okay to leave the length in there.
|
||||
@ -316,7 +318,7 @@ def pointInIsland(pt, island):
|
||||
|
||||
|
||||
# box is (left,bottom, right, top)
|
||||
def islandIntersectUvIsland(source, target, xSourceOffset, ySourceOffset):
|
||||
def islandIntersectUvIsland(source, target, SourceOffset):
|
||||
# Is 1 point in the box, inside the vertLoops
|
||||
edgeLoopsSource = source[6] # Pretend this is offset
|
||||
edgeLoopsTarget = target[6]
|
||||
@ -324,28 +326,20 @@ def islandIntersectUvIsland(source, target, xSourceOffset, ySourceOffset):
|
||||
# Edge intersect test
|
||||
for ed in edgeLoopsSource:
|
||||
for seg in edgeLoopsTarget:
|
||||
xi, yi = lineIntersection2D(\
|
||||
seg[0][0], seg[0][1], seg[1][0], seg[1][1],\
|
||||
xSourceOffset+ed[0][0], ySourceOffset+ed[0][1], xSourceOffset+ed[1][0], ySourceOffset+ed[1][1])
|
||||
if xi != None:
|
||||
i = Geometry.LineIntersect2D(\
|
||||
seg[0], seg[1], SourceOffset+ed[0], SourceOffset+ed[1])
|
||||
if i:
|
||||
return 1 # LINE INTERSECTION
|
||||
|
||||
# 1 test for source being totally inside target
|
||||
SourceOffset.resize3D()
|
||||
for pv in source[7]:
|
||||
p = pv.__copy__()
|
||||
|
||||
p.x += xSourceOffset
|
||||
p.y += ySourceOffset
|
||||
if pointInIsland(p, target[0]):
|
||||
if pointInIsland(pv+SourceOffset, target[0]):
|
||||
return 2 # SOURCE INSIDE TARGET
|
||||
|
||||
# 2 test for a part of the target being totaly inside the source.
|
||||
for pv in target[7]:
|
||||
p = pv.__copy__()
|
||||
|
||||
p.x -= xSourceOffset
|
||||
p.y -= ySourceOffset
|
||||
if pointInIsland(p, source[0]):
|
||||
if pointInIsland(pv+SourceOffset, source[0]):
|
||||
return 3 # PART OF TARGET INSIDE SOURCE.
|
||||
|
||||
return 0 # NO INTERSECTION
|
||||
@ -457,7 +451,6 @@ def optiRotateUvIsland(faces):
|
||||
for ROTMAT in RotMatStepRotation:
|
||||
uvVecs = best2dRotation(uvVecs, ROTMAT[0], ROTMAT[1])
|
||||
|
||||
|
||||
# Only if you want it, make faces verticle!
|
||||
if currentArea[1] > currentArea[2]:
|
||||
# Rotate 90d
|
||||
@ -616,7 +609,7 @@ def mergeUvIslands(islandList, islandListArea):
|
||||
|
||||
##testcount+=1
|
||||
#print 'Testing intersect'
|
||||
Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, boxLeft, boxBottom)
|
||||
Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector(boxLeft, boxBottom))
|
||||
#print 'Done', Intersect
|
||||
if Intersect == 1: # Line intersect, dont bother with this any more
|
||||
pass
|
||||
@ -655,8 +648,7 @@ def mergeUvIslands(islandList, islandListArea):
|
||||
# targetIsland[6].extend(sourceIsland[6])
|
||||
#while sourceIsland[6]:
|
||||
targetIsland[6].extend( [ (\
|
||||
((e[0][0]+boxLeft, e[0][1]+boxBottom),\
|
||||
(e[1][0]+boxLeft, e[1][1]+boxBottom), e[2])\
|
||||
(e[0]+offset, e[1]+offset, e[2])\
|
||||
) for e in sourceIsland[6] ] )
|
||||
|
||||
sourceIsland[6][:] = [] # Empty
|
||||
|
@ -45,13 +45,19 @@
|
||||
/* needed for EXPP_ReturnPyObjError and EXPP_check_sequence_consistency */
|
||||
#include "gen_utils.h"
|
||||
|
||||
//#include "util.h" /* MIN2 and MAX2 */
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#define SWAP_FLOAT(a,b,tmp) tmp=a; a=b; b=tmp
|
||||
#define eul 0.000001
|
||||
/*-------------------------DOC STRINGS ---------------------------*/
|
||||
static char M_Geometry_doc[] = "The Blender Geometry module\n\n";
|
||||
static char M_Geometry_PolyFill_doc[] = "(veclist_list) - takes a list of polylines (each point a vector) and returns the point indicies for a polyline filled with triangles";
|
||||
static char M_Geometry_LineIntersect2D_doc[] = "(lineA_p1, lineA_p2, lineB_p1, lineB_p2) - takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None";
|
||||
/*-----------------------METHOD DEFINITIONS ----------------------*/
|
||||
struct PyMethodDef M_Geometry_methods[] = {
|
||||
{"PolyFill", ( PyCFunction ) M_Geometry_PolyFill, METH_VARARGS, M_Geometry_PolyFill_doc},
|
||||
{"LineIntersect2D", ( PyCFunction ) M_Geometry_LineIntersect2D, METH_VARARGS, M_Geometry_LineIntersect2D_doc},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
/*----------------------------MODULE INIT-------------------------*/
|
||||
@ -66,7 +72,7 @@ PyObject *Geometry_Init(void)
|
||||
|
||||
/*----------------------------------Geometry.PolyFill() -------------------*/
|
||||
/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */
|
||||
PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * args )
|
||||
static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * args )
|
||||
{
|
||||
PyObject *tri_list; /*return this list of tri's */
|
||||
PyObject *polyLineSeq, *polyLine, *polyVec;
|
||||
@ -164,3 +170,98 @@ PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * args )
|
||||
|
||||
return tri_list;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
|
||||
{
|
||||
VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
|
||||
float a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, c1,c2, det_inv, m1, m2, newvec[2];
|
||||
if( !PyArg_ParseTuple ( args, "O!O!O!O!",
|
||||
&vector_Type, &line_a1,
|
||||
&vector_Type, &line_a2,
|
||||
&vector_Type, &line_b1,
|
||||
&vector_Type, &line_b2)
|
||||
)
|
||||
return ( EXPP_ReturnPyObjError
|
||||
( PyExc_TypeError, "expected 4 vector types\n" ) );
|
||||
|
||||
a1x= line_a1->vec[0];
|
||||
a1y= line_a1->vec[1];
|
||||
a2x= line_a2->vec[0];
|
||||
a2y= line_a2->vec[1];
|
||||
|
||||
b1x= line_b1->vec[0];
|
||||
b1y= line_b1->vec[1];
|
||||
b2x= line_b2->vec[0];
|
||||
b2y= line_b2->vec[1];
|
||||
|
||||
if((MIN2(a1x, a2x) > MAX2(b1x, b2x)) ||
|
||||
(MAX2(a1x, a2x) < MIN2(b1x, b2x)) ||
|
||||
(MIN2(a1y, a2y) > MAX2(b1y, b2y)) ||
|
||||
(MAX2(a1y, a2y) < MIN2(b1y, b2y)) ) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
/* Make sure the hoz/vert line comes first. */
|
||||
if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) {
|
||||
SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/
|
||||
SWAP_FLOAT(a1y, b1y, xi);
|
||||
SWAP_FLOAT(a2x, b2x, xi);
|
||||
SWAP_FLOAT(a2y, b2y, xi);
|
||||
}
|
||||
|
||||
if (fabs(a1x-a2x) < eul) { /* verticle line */
|
||||
if (fabs(b1x-b2x) < eul){ /*verticle second line */
|
||||
Py_RETURN_NONE; /* 2 verticle lines dont intersect. */
|
||||
}
|
||||
else if (fabs(b1y-b2y) < eul) {
|
||||
/*X of vert, Y of hoz. no calculation needed */
|
||||
newvec[0]= a1x;
|
||||
newvec[1]= b1y;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
}
|
||||
|
||||
yi = ((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x));
|
||||
|
||||
if (yi > MAX2(a1y, a2y)) {/* New point above seg1's vert line */
|
||||
Py_RETURN_NONE;
|
||||
} else if (yi < MIN2(a1y, a2y)) { /* New point below seg1's vert line */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
newvec[0]= a1x;
|
||||
newvec[1]= yi;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
} else if (fabs(a2y-a1y) < eul) { /* hoz line1 */
|
||||
if (fabs(b2y-b1y) < eul) { /*hoz line2*/
|
||||
Py_RETURN_NONE; /*2 hoz lines dont intersect*/
|
||||
}
|
||||
|
||||
/* Can skip vert line check for seg 2 since its covered above. */
|
||||
xi = ((b1x / fabs(b1y - b2y)) * fabs(b2y - a1y)) + ((b2x / fabs(b1y - b2y)) * fabs(b1y - a1y));
|
||||
if (xi > MAX2(a1x, a2x)) { /* New point right of hoz line1's */
|
||||
Py_RETURN_NONE;
|
||||
} else if (xi < MIN2(a1x, a2x)) { /*New point left of seg1's hoz line */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
newvec[0]= xi;
|
||||
newvec[1]= a1y;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
}
|
||||
|
||||
b1 = (a2y-a1y)/(a2x-a1x);
|
||||
b2 = (b2y-b1y)/(b2x-b1x);
|
||||
a1 = a1y-b1*a1x;
|
||||
a2 = b1y-b2*b1x;
|
||||
|
||||
if (b1 - b2 == 0.0) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
xi = - (a1-a2)/(b1-b2);
|
||||
yi = a1+b1*xi;
|
||||
if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) {
|
||||
newvec[0]= xi;
|
||||
newvec[1]= yi;
|
||||
return newVectorObject(newvec, 2, Py_NEW);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
@ -38,6 +38,7 @@
|
||||
#include "vector.h"
|
||||
|
||||
PyObject *Geometry_Init( void );
|
||||
PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * args );
|
||||
static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args );
|
||||
|
||||
#endif /* EXPP_Geometry_H */
|
||||
|
@ -43,3 +43,10 @@ def PolyFill(polylines):
|
||||
|
||||
Blender.Redraw()
|
||||
"""
|
||||
|
||||
def LineIntersect2D(vec1, vec2, vec3, vec4):
|
||||
"""
|
||||
Takes 2 lines vec1, vec2 for the 2 points of the first line and vec2, vec3 for the 2 points of the second line.
|
||||
@rtype: Vector
|
||||
@return: a 2D Vector for the intersection or None where there is no intersection.
|
||||
"""
|
Loading…
Reference in New Issue
Block a user