Changeset 1217


Ignore:
Timestamp:
Apr 11, 2005, 6:23:47 PM (20 years ago)
Author:
prow
Message:

Nearly working polygon from triangles.

Location:
inundation/ga/storm_surge/pmesh
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • inundation/ga/storm_surge/pmesh/mesh.py

    r1183 r1217  
    21172117                          colour = colour)
    21182118
    2119 
    21202119    def weed(self,Vertices,Segments):
    21212120        #weed out existing duplicates
     
    21292128            point = (vertex.x,vertex.y)
    21302129            point_keys[point]=vertex
     2130        #inlined would looks very ugly
    21312131
    21322132        line_keys = {}
     
    21512151        return Vertices,Segments
    21522152
     2153    def segs_to_dict(self,segments):
     2154        dict={}
     2155        for segment in segments:
     2156            vertex1 = segment.vertices[0]
     2157            vertex2 = segment.vertices[1]
     2158            point1 = (vertex1.x,vertex1.y)
     2159            point2 = (vertex2.x,vertex2.y)
     2160            line = (point1,point2)
     2161            dict[line]=segment
     2162        return dict
     2163
     2164    def seg2line(self,s):
     2165        return ((s.vertices[0].x,s.vertices[0].y,)\
     2166                (s.vertices[1].x,s.vertices[1].y))
     2167
     2168    def line2seg(self,line,tag=None):
     2169        point0 = self.ver2point(line[0])
     2170        point1 = self.ver2point(line[1])
     2171        return Segment(point0,point1,tag=tag)
     2172
     2173    def ver2point(self,vertex):
     2174        return (vertex.x,vertex.y)
     2175
     2176    def point2ver(self,point):
     2177        return Vertex(point[0],point[1])
     2178
    21532179    def triangles_to_polySet(self,setName):
     2180        seg2line = self.seg2line
     2181        ver2point = self.ver2point
     2182        line2seg = self.line2seg
     2183        point2ver = self.point2ver
     2184
     2185        from Numeric import array,allclose
    21542186        #turn the triangles into a set
    21552187        Triangles = self.sets[self.setID[setName]]
     
    21582190            Triangles_dict[triangle]=None
    21592191
     2192        point_keys = {}
     2193        userVertices={}
     2194        for vertex in self.getUserVertices():
     2195            point = ver2point(vertex)
     2196            if not point_keys.has_key(point):
     2197                point_keys[point]=vertex
     2198                userVertices[vertex]=True
     2199
     2200        userSegments = self.segs_to_dict(self.userSegments)
     2201        affine_lines = Affine_Linespace()
     2202        for line in userSegments.keys():
     2203            affine_lines.append(line)
     2204
     2205        alphaSegments = self.segs_to_dict(self.alphaUserSegments)
     2206        for line in alphaSegments.keys():
     2207            affine_lines.append(line)
     2208       
     2209        for triangle in Triangles:
     2210            for i in (0,1,2):
     2211                #for every triangles neighbour:
     2212                if not Triangles_dict.has_key(triangle.neighbors[i]):
     2213                #if the neighbour is not in the set:
     2214                    a = triangle.vertices[i-1]
     2215                    b = triangle.vertices[i-2]
     2216                    for vert in (a,b):
     2217                        point = ver2point(vert)
     2218                        if not point_keys.has_key(point):
     2219                            userVertices[vert]=True
     2220                            point_keys[point]=vert
     2221
     2222                    #Get possible matches:
     2223                    point_a = ver2point(a)
     2224                    point_b = ver2point(b)
     2225                    midpoint = ((a.x+b.x)/2,(a.y+b.y)/2)
     2226                    line = (point_a,point_b)
     2227                    tag = None
     2228                    possible_lines = affine_lines[line]
     2229                    found = 0                           
     2230                    for user_line in possible_lines:
     2231                        if self.point_on_line(midpoint,user_line):
     2232                            if user_line in userSegments:
     2233                                parent_segment = userSegments.pop(user_line)
     2234                            else:
     2235                                parent_segment = alphaSegments.pop(user_line)
     2236                            tag = parent_segment.tag
     2237                            offspring = [line]
     2238                            offspring.extend(self.subtract_line(user_line,line))
     2239                            affine_lines.remove(user_line)
     2240                            for newline in offspring:
     2241                                line_vertices = []
     2242                                for point in newline:
     2243                                    if point_keys.has_key(point):
     2244                                        vert = point_keys[point]
     2245                                    else:
     2246                                        vert = Vertex(point[0],point[1])
     2247                                        userVertices[vert]=True
     2248                                        point_keys[point]=vert
     2249                                    line_vertices.append(vert)
     2250                                segment = Segment(line_vertices[0],line_vertices[1],tag)
     2251                                userSegments[newline]=segment
     2252                                affine_lines.append(newline)
     2253                            found=1
     2254                            break
     2255                    if not found:
     2256                        line_vertices = []
     2257                        for point in line:
     2258                            if point_keys.has_key(point):
     2259                                vert = point_keys[point]
     2260                            else:
     2261                                vert = Vertex(point[0],point[1])
     2262                                userVertices[vert]=True
     2263                                point_keys[point]=vert
     2264                            line_vertices.append(vert)
     2265                        segment = Segment(line_vertices[0],line_vertices[1],tag)
     2266                        userSegments[line]=segment
     2267                        affine_lines.append(line)
     2268       
     2269        self.userVerticies = []
     2270        self.userSegments = []
     2271        self.alphaSegments = []
     2272        #for key in userSegments.keys():
     2273        #    self.userSegments.append(userSegments[key])
     2274
     2275        #for key in alphaSegments.keys():
     2276        #    self.userSegments.append(alphaSegments[key])
     2277        #FIXME change alpha to user and sync with pmesh
     2278        #ie self.alphaSegments.append(alphaSegments[key])
     2279
     2280        return userVertices,userSegments,alphaSegments
     2281
     2282    def subtract_line(self,parent,child):
     2283        #Subtracts child from parent
     2284        #Requires that the child is a
     2285        #subline of parent to work.
     2286
     2287        from Numeric import allclose,dot,array
     2288        A= parent[0]
     2289        B= parent[1]
     2290        a = child[0]
     2291        b = child[1]
     2292
     2293        A_array = array(parent[0])
     2294        B_array = array(parent[1])
     2295        a_array   = array(child[0])
     2296        b_array   = array(child[1])
     2297
     2298        assert not A == B
     2299        assert not a == b
     2300
     2301        answer = []
     2302
     2303        if not (allclose(A_array,a_array)\
     2304             or allclose(B_array,b_array)\
     2305             or allclose(A_array,b_array)\
     2306             or allclose(a_array,B_array)):
     2307            if dot(A_array-a_array,A_array-a_array) \
     2308            < dot(A_array-b_array,A_array-b_array):
     2309                sibling1 = (A,a)
     2310                sibling2 = (B,b)
     2311                return [sibling1,sibling2]
     2312            else:
     2313                sibling1 = (A,b)
     2314                sibling2 = (B,a)
     2315                return [sibling1,sibling2]
     2316
     2317        elif allclose(A_array,a_array):
     2318            if allclose(B_array,b_array):
     2319                return []
     2320            else:
     2321                sibling = (b,B)
     2322                return [sibling]
     2323        elif allclose(B_array,b_array):
     2324            sibling = (a,A)
     2325            return [sibling]
     2326
     2327        elif allclose(A_array,b_array):
     2328            if allclose(B,a):
     2329                return []
     2330            else:
     2331                sibling = (a,B)
     2332                return [sibling]
     2333        elif allclose(a_array,B_array):
     2334            sibling = (b,A)
     2335            return [sibling]
     2336
     2337
     2338    def point_on_line(self,point,line):
     2339        x=point[0]
     2340        y=point[1]
     2341        x0=line[0][0]
     2342        x1=line[1][0]
     2343        y0=line[0][1]
     2344        y1=line[1][1]
     2345        return point_on_line(x,y,x0,y0,x1,y1)
     2346        #a wrapper for the c func.
     2347
     2348    def line_length(self,line):
     2349        x0=line[0][0]
     2350        x1=line[1][0]
     2351        y0=line[0][1]
     2352        y1=line[1][1]
     2353        return ((x1-x0)**2-(y1-y0)**2)**0.5     
     2354
     2355    def triangles_to_polySet2(self,setName):
     2356        from Numeric import array,allclose
     2357
     2358        #turn the triangles into a set
     2359        Triangles = self.sets[self.setID[setName]]
     2360        Triangles_dict = {}
     2361        for triangle in Triangles:
     2362            Triangles_dict[triangle]=None
     2363
    21602364        userVertices = {}
    2161         userSegments = []
     2365        userSegments = {}
    21622366        point_keys = {}
     2367        affine_lines = {}
    21632368        for vertex in self.getUserVertices():
    21642369            point = (vertex.x,vertex.y)
     
    21672372        line_keys = {}
    21682373        for segment in self.getUserSegments():
     2374        #inlined would looks very ugly
    21692375            vertex1 = segment.vertices[0]
    21702376            vertex2 = segment.vertices[1]
     
    21792385            line1 = (point1,point2)
    21802386            line2 = (point2,point1)
     2387            AB = affine_line(point1,point2)
     2388            flat_AB_up = ceilAB[0]+AB[1]+AB[2]
    21812389            if not (line_keys.has_key(line1) \
    21822390                 or line_keys.has_key(line2)):
     
    22092417                        b=point_keys[(b.x,b.y)]
    22102418                        userVertices[b]=point_keys[(b.x,b.y)]
    2211                     assert userVertices.has_key(b) 
     2419                    assert userVertices.has_key(b)
    22122420
    22132421                    if not (line_keys.has_key(((a.x,a.y),(b.x,b.y)))\
     
    22172425                        assert ((a.x,a.y)!=(b.x,b.y))
    22182426                        assert a!=b
    2219                         userSegments.append(Segment(a,b))
     2427                        AB = affine_line(a,b)
     2428                        flat_AB = AB[0]+AB[1]+AB[2]
     2429                        if affine_lines.has_key(flat_AB):
     2430                            userSegments[Segment(a,b)]=None
    22202431                        line_keys[((a.x,a.y),(b.x,b.y))]=None
    22212432
    2222         userVertices,userSegments = self.weed(userVertices.keys(),userSegments)
     2433        userVertices,userSegments = self.weed(userVertices.keys(),userSegments.keys())
    22232434        self.userVertices.extend(userVertices)
    22242435        self.userSegments.extend(userSegments)
     
    22962507        self.meshTriangles[i]=replacement
    22972508        assert replacement in self.meshTriangles
    2298 
    2299 
    2300 
    23012509
    23022510def importUngenerateFile(ofile):
     
    28343042
    28353043    def repairCaseOne(self):
    2836         r = self.r
     3044        r = self.rkey
    28373045
    28383046
     
    28973105        triangle1.neighbors[j]=triangle2
    28983106
    2899          
    2900 
     3107class Discretised_Tuple_Set:
     3108    """
     3109    if a={(0.0):[(0.01),(0.02)],(0.2):[(0.17)]}
     3110    a[(0.01)]=a[(0.0)]=[(0.01),(0.02)]
     3111    a[(10000)]=[] #NOT KEYERROR
     3112
     3113    a.append[(0.01)]
     3114    => {0.0:[(0.01),(0.02),(0.01)],0.2:[(0.17)]}
     3115
     3116    #NOT IMPLIMENTED
     3117    a.remove[(0.01)]
     3118    => {(0.0):[(0.02),(0.01)],0.2:[(0.17)]}
     3119
     3120    a.remove[(0.17)]
     3121    => {(0.0):[(0.02),(0.01)],0.2:[]}
     3122    #NOT IMPLIMENTED
     3123    at a.precision = 2:
     3124        a.round_up[0.0]=
     3125        a.round_flat[0.0]=
     3126        a.round_downp0.0]=
     3127
     3128        a.up((0.1,2.04))=
     3129
     3130    If tolerance = 0, nothing gets rounded into
     3131    two bins. If tolerance = 0.5, everything does.
     3132
     3133    Ideally, precision can be set high, so that multiple
     3134    entries are rarely in the same bin. And tolerance should
     3135    be low (<0.1 for 1 dimension!,<(0.1/n) for small n!!)
     3136    so that it is rare to put items in mutiple bins.
     3137
     3138    Ex bins per entry = product(a,b,c...,n)
     3139    a = 1 or 2 s.t. Ex(a) = 1+2*tolerance
     3140    b = 1 or 2 ...
     3141
     3142    BUT!!! to avoid missing the right bin:
     3143    (-10)**(precision+1)*tolerance must be greater than the
     3144    greatest possible variation that an identical element
     3145    can display.
     3146    """
     3147    def __init__(self,precision = 6,tolerance = 0.01):
     3148        self.__precision__ = precision
     3149        self.__tolerance__ = tolerance
     3150        assert tolerance <= 0.5
     3151        self.__items__ = {}
     3152        from math import frexp
     3153        self.frexp = frexp
     3154
     3155    def __repr__(self):
     3156        return '%s'%self.__items__
     3157
     3158    def rounded_keys(self,key):
     3159        key = tuple(key)
     3160        keys = [key]
     3161        keys = self.__rounded_keys__(key)
     3162        return (keys)
     3163
     3164    def __rounded_keys__(self,key):
     3165        keys = []
     3166        up_key=list(key)
     3167        for i in range(len(up_key)):
     3168            up_key[i]=self.round_up(key[i])
     3169        keys.append(tuple(up_key))
     3170
     3171        #round down the value
     3172        for i in range(len(up_key)):
     3173            if not keys[0][i]==self.round_down(key[i]):
     3174            #unless round_up = round_down
     3175            #so the keys stay unique
     3176                for j in range(len(keys)):
     3177                    down_key = list(keys[j])
     3178                    down_key[i]=self.round_down(key[i])
     3179                    down_key=tuple(down_key)
     3180                    keys.append(down_key)
     3181        return keys
     3182
     3183    def append(self,item):
     3184        keys = self.rounded_keys(item)
     3185        for key in keys:
     3186            if self.__items__.has_key(key):
     3187                self.__items__[key].append(item)
     3188            else:
     3189                self.__items__[key]=[item]
     3190
     3191    def __getitem__(self,key):
     3192        answer = []
     3193        keys = self.rounded_keys(key)
     3194        for key in keys:
     3195            if self.__items__.has_key(key):
     3196                answer.extend(self.__items__[key])
     3197        #if len(answer)==0:
     3198        #    raise KeyError#FIXME or return KeyError
     3199        #                  #FIXME or just return []?
     3200        else:
     3201            return answer #FIXME or unique(answer)?
     3202
     3203    def __delete__(self,item):
     3204        keys = self.rounded_keys(item)
     3205        answer = False
     3206        #if any of the possible keys contains
     3207        #a list, return true
     3208        for key in keys:       
     3209            if self.__items__.has_key(key):
     3210                if item in self.__items__[key]:
     3211                    self.__items__[key].remove(item)
     3212
     3213    def remove(self,item):
     3214        self.__delete__(item)
     3215
     3216    def __contains__(self,item):
     3217
     3218        keys = self.rounded_keys(item)
     3219        answer = False
     3220        #if any of the possible keys contains
     3221        #a list, return true
     3222        for key in keys:       
     3223            if self.__items__.has_key(key):
     3224                if item in self.__items__[key]:
     3225                    answer = True
     3226        return answer
     3227
     3228
     3229    def has_item(self,item):
     3230        return self.__contains__(item)
     3231
     3232    def round_up(self,value):
     3233         tolerance=self.__tolerance__
     3234         #Rounding up the value
     3235         m,e = self.frexp(value)
     3236         #m is the mantissa, e the exponent
     3237         # 0.5 < |m| < 1.0
     3238         m = m*(1+tolerance*(10**-(self.__precision__+1))/((m**2)**0.5))
     3239         #bump m up, by 5% or whatever
     3240         #self.precision dictates
     3241         m = round(m,self.__precision__)
     3242     #round m off so that the bump up
     3243     #will be discernable if and only if
     3244         return m*(2.**e)
     3245
     3246    def round_down(self,value):
     3247         tolerance=self.__tolerance__
     3248         #Rounding down the value
     3249         m,e = self.frexp(value)
     3250         #m is the mantissa, e the exponent
     3251         # 0.5 < m < 1.0
     3252         m = m*(1-tolerance*(10**-(self.__precision__+1))/((m**2)**0.5))
     3253         #bump the |m| down, by 5% or whatever
     3254         #self.precision dictates
     3255         m = round(m,self.__precision__)
     3256     #round m off so that the bump down
     3257     #will be discernable if and only if
     3258         return m*(2.**e)
     3259
     3260    def round_flat(self,value):
     3261    #redundant
     3262         m,e = self.frexp(value)
     3263         m = round(m,self.__precision__)
     3264         return m*(2.**e)
     3265
     3266    def keys(self):
     3267        return self.__items__.keys()
     3268
     3269   
     3270
     3271
     3272class Mapped_Discretised_Tuple_Set(Discretised_Tuple_Set):
     3273    """
     3274    This is a discretised tuple set, but
     3275    based on a mapping. The mapping MUST
     3276    return a sequence.
     3277
     3278    example:
     3279    def weight(animal):
     3280        return [animal.weight]
     3281   
     3282    a = Mapped_Discretised_Tuple_Set(weight)
     3283    a.append[cow]
     3284    a.append[fox]
     3285    a.append[horse]
     3286
     3287    a[horse]    -> [cow,horse]
     3288    a[dog]      -> [fox]
     3289    a[elephant] -> []
     3290    """
     3291    def __init__(self,mapping,precision = 6, tolerance=0.01):
     3292        Discretised_Tuple_Set.__init__\
     3293         (self,precision,tolerance = tolerance)
     3294        self.mapping = mapping
     3295
     3296    def rounded_keys(self,key):
     3297        mapped_key = tuple(self.mapping(key))
     3298        keys = self.__rounded_keys__(mapped_key)
     3299        return keys
     3300
     3301class Affine_Linespace(Mapped_Discretised_Tuple_Set):
     3302    """
     3303    The affine linespace creates a way to record and compare lines.
     3304    Precision is a bit of a hack, but it creates a way to avoid
     3305    misses caused by round offs (between two lines of different
     3306    lenghts, the short one gets rounded off more).
     3307    I am starting to think that a quadratic search would be faster.
     3308    Nearly.
     3309    """
     3310    def __init__(self,precision = 4,tolerance=0.04):
     3311        Mapped_Discretised_Tuple_Set.__init__\
     3312            (self,self.affine_line,\
     3313            precision=precision,tolerance=tolerance)
     3314
     3315    def affine_line(self,line):
     3316        point_1 = line[0]
     3317        point_2 = line[1]
     3318        #returns the equation of a line
     3319        #between two points, in the from
     3320        #(a,b,-c), as in ax+by-c=0
     3321        #or line *dot* (x,y,1) = (0,0,0)
     3322
     3323        #Note that it normalises the line
     3324        #(a,b,-c) so Line*Line = 1.
     3325        #This does not change the mathematical
     3326        #properties, but it makes comparism
     3327        #easier.
     3328
     3329        #There are probably better algorithms.
     3330        x1 = point_1[0]
     3331        x2 = point_2[0]
     3332        y1 = point_1[1]
     3333        y2 = point_2[1]
     3334        dif_x = x1-x2
     3335        dif_y = y1-y2
     3336
     3337        if dif_x == dif_y == 0:
     3338            msg = 'points are the same'
     3339            raise msg
     3340        elif abs(dif_x)>=abs(dif_y):
     3341            alpha = (-dif_y)/dif_x
     3342            #a = alpha * b
     3343            b = 1.
     3344            c = (x1*alpha+x2*alpha+y1+y2)/2.
     3345            a = alpha*b
     3346        else:
     3347            beta = dif_x/(-dif_y)
     3348            #b = beta * a
     3349            a = 1.
     3350            c = (x1+x2+y1*beta+y2*beta)/2.
     3351            b = beta*a
     3352
     3353        mag = (a**2+b**2+c**2)**(0.5)
     3354
     3355        if a == 0:
     3356            sign_a = 1.
     3357        else:
     3358            sign_a = a/((a**2)**0.5)
     3359        if b == 0:
     3360            sign_b = 1.
     3361        else:
     3362            sign_b = b/((b**2)**0.5)
     3363        if c == 0:
     3364            sign_c = 1.
     3365        else:
     3366            sign_c = c/((c**2)**0.5)
     3367        a = a/mag*sign_a
     3368        b = b/mag*sign_b
     3369        c = c/mag*sign_c
     3370        return a,b,c
     3371
     3372   
    29013373if __name__ == "__main__":
    29023374    #from mesh import *
  • inundation/ga/storm_surge/pmesh/pmesh.py

    r1177 r1217  
    339339
    340340    def triangles_to_polySet(self,parent):
    341         self.mesh.triangles_to_polySet(self.selSet)
    342         #event = None
    343         #for v in vertices.keys():
    344         #    if vertices[v] is True:
    345         #        x = v.x*self.SCALE
    346         #        y = v.y*self.SCALE
    347         #        vertices[v]=self.drawVertex(x,y,event)
    348         #print 'segments'
    349         #print segments
    350         #print 'vertices.keys()'
    351         #print vertices.keys()
    352         #for s in segments:
    353         #    v0 = vertices[s[0]]
    354         #    v1 = vertices[s[1]]
    355         #    self.drawSegment(v0,v1)
     341        userVertices,userSegments,alphaSegments = \
     342            self.mesh.triangles_to_polySet(self.selSet)
     343
    356344        self.canvas.delete(ALL)
     345
     346        self.Vertices = visualmesh.vPoints(mesh.Vertex)
     347        self.Segments = visualmesh.vSegments(mesh.Segment)
     348
     349        event = None
     350        print 'len(userVertices.keys())'
     351        print len(userVertices.keys())
     352        print 'len(userSegments.keys())'
     353        print len(userSegments.keys())
     354        print 'len(alphaSegments.keys())'
     355        print len(alphaSegments.keys())
     356        for v in userVertices.keys():
     357            if userVertices[v] is True:
     358                x = v.x*self.SCALE
     359                y = v.y*self.SCALE
     360                userVertices[(v.x,v.y)]=self.drawVertex(x,y,event)
     361
     362        for line in userSegments.keys():
     363            v0 = userVertices[line[0]]
     364            v1 = userVertices[line[1]]
     365            segment = self.drawSegment(v0,v1)
     366            segment.set_tag(userSegments[line].tag)
     367
     368        for line in alphaSegments.keys():
     369            v0 = userVertices[line[0]]
     370            v1 = userVertices[line[1]]
     371            segment = self.drawSegment(v0,v1)
     372            segment.set_tag(alphaSegments[line].tag)
    357373        self.visualiseMesh(self.mesh)
    358374
     
    458474        region = self.drawRegion(x_origin, y_origin, 0)
    459475        region.setTag("setheight5")
     476
     477       
    460478       
    461479        x_origin = 30
Note: See TracChangeset for help on using the changeset viewer.