def same_side(lp): lp0d = dpv.distance(lp[ 0],tip) lp1d = dpv.distance(lp[-1],tip) lpt = lp[0] if lp0d < lp1d else lp[-1] s1,s2 = tiptail(le.rpts,ne.rpts) segsect = dpr.segments_intersect_noncolinear(s1,s2,lpt,tip) if not segsect:return lpt
def calculate(self, roads): for r in roads: pstd = dpv.distance(self.p, r.start) pend = dpv.distance(self.p, r.end) if pend < pstd: r.end.translate(r.tip.copy().flip().scale_u(10)) else: r.start.translate(r.tail.copy().scale_u(10)) r.calculate()
def face_away(self, side): rp = side[1]['room'] intpt = dpv.vector(rp[1]['x'], rp[1]['y'], 0.0) midpt = dpv.midpoint(*side[0]) tangt = dpv.v1_v2(*side[0]).normalize() norml = tangt.copy().rotate_z(dpr.rad(90)).normalize() tstpt = midpt.copy().translate(norml) side[1]['normal'] = norml if dpv.distance(intpt, midpt) > dpv.distance(intpt, tstpt): side[1]['normal'].flip()
def tiptail(el1,el2): d1 = dpv.distance(el1[ 0],el2[ 0]) d2 = dpv.distance(el1[ 0],el2[-1]) d3 = dpv.distance(el1[-1],el2[ 0]) d4 = dpv.distance(el1[-1],el2[-1]) md = min(d1,d2,d3,d4) if md == d1:return el1[ 0],el2[ 0] elif md == d2:return el1[ 0],el2[-1] elif md == d3:return el1[-1],el2[ 0] elif md == d4:return el1[-1],el2[-1]
def face_away(self,side): rp = side[1]['room'] intpt = dpv.vector(rp[1]['x'],rp[1]['y'],0.0) midpt = dpv.midpoint(*side[0]) tangt = dpv.v1_v2(*side[0]).normalize() norml = tangt.copy().rotate_z(dpr.rad(90)).normalize() tstpt = midpt.copy().translate(norml) side[1]['normal'] = norml if dpv.distance(intpt,midpt) > dpv.distance(intpt,tstpt): side[1]['normal'].flip()
def wall(p1, p2, wh1, wh2, ww, doors=(), windows=()): l = dpv.distance(p1, p2) a = dpr.angle_from_xaxis_xy(dpv.v1_v2(p1, p2)) ww2 = ww / 2.0 bnd = [ dpv.vector(ww2, 0, 0), dpv.vector(l - ww2, 0, 0), dpv.vector(l - ww2, wh2, 0), dpv.vector(ww2, wh1, 0) ] for d in doors: dhp = doorhole(l, *d) for x in range(len(dhp) - 1, -1, -1): bnd.insert(1, dhp[x]) wholes = [tuple(windowhole(l, *w)) for w in windows] extras = [] for d in doors: dpolys = doorframe(l, *d) for dp in dpolys: extras.append(dp) for w in windows: wpolys = windowframe(l, *w) for wp in wpolys: extras.append(wp) x = dpv.z().scale_u(ww2) main0 = (tuple(bnd), tuple(wholes)) main1 = dpr.translate_polygon(dpr.copy_polygon(main0), x) dpr.translate_polygon(main0, x.flip()) wallgons = (main0, main1) + tuple(extras) #wallgons = (main1,)+tuple(extras) for wgon in wallgons: dpr.rotate_x_polygon(wgon, dpr.PI / 2.0) dpr.rotate_z_polygon(wgon, a) dpr.translate_polygon(wgon, p1) return wallgons
def inside_circle_xy(pt,center,radius): dzero = dpv.zero() dzhat = dpv.zhat pt = pt.project_plane(dzero,dzhat) center = center.project_plane(dzero,dzhat) ins = not dpv.distance(pt,center) > radius return ins
def wall(p1,p2,wh1,wh2,ww,doors = (),windows = ()): l = dpv.distance(p1,p2) a = dpr.angle_from_xaxis_xy(dpv.v1_v2(p1,p2)) ww2 = ww/2.0 bnd = [ dpv.vector( ww2, 0,0),dpv.vector(l-ww2, 0,0), dpv.vector(l-ww2,wh2,0),dpv.vector( ww2,wh1,0)] for d in doors: dhp = doorhole(l,*d) for x in range(len(dhp)-1,-1,-1): bnd.insert(1,dhp[x]) wholes = [tuple(windowhole(l,*w)) for w in windows] extras = [] for d in doors: dpolys = doorframe(l,*d) for dp in dpolys:extras.append(dp) for w in windows: wpolys = windowframe(l,*w) for wp in wpolys:extras.append(wp) x = dpv.z().scale_u(ww2) main0 = (tuple(bnd),tuple(wholes)) main1 = dpr.translate_polygon(dpr.copy_polygon(main0),x) dpr.translate_polygon(main0,x.flip()) wallgons = (main0,main1)+tuple(extras) #wallgons = (main1,)+tuple(extras) for wgon in wallgons: dpr.rotate_x_polygon(wgon,dpr.PI/2.0) dpr.rotate_z_polygon(wgon,a) dpr.translate_polygon(wgon,p1) return wallgons
def _endpoints(self,v1,v2): self.v1 = v1.copy() self.v2 = v2.copy() self.l = dpv.distance(v1,v2) self.center = dpv.midpoint(v1,v2) self.tangent = dpv.v1_v2(v1,v2).normalize() self.normal = self.tangent.copy() self.normal.rotate_z(dpr.rad(90)).normalize()
def _add_gap(self,g1,g2): def inside(x1,x2,x3): d12 = dpv.distance(x1,x2) d13 = dpv.distance(x1,x3) d23 = dpv.distance(x2,x3) if d13 <= d12 and d23 <= d12:return True else:return False g1d = min([dpv.distance(g1,self.v1),dpv.distance(g1,self.v2)]) g2d = min([dpv.distance(g2,self.v1),dpv.distance(g2,self.v2)]) # skip if gap is too close to edges if g1d < 2 or g2d < 2:return None # skip if gap overlaps existing gap for g in self.gaps: og1,og2 = g if inside(og1,og2,g1) or inside(og1,og2,g2): return None self.gaps.append((g1,g2)) return g1,g2
def edge_lengths(self): elengths = {} for edx in range(self.edgecount): e = self.edges[edx] if e is None or e in elengths:continue ep1,ep2 = self.points.get_points(*e) d = dpv.distance(ep1,ep2) elengths[e] = d elengths[e[::-1]] = d return elengths
def circumscribe_tri(p1,p2,p3,plane = None): if not plane is None: p1 = p1.project_plane(*plane) p2 = p2.project_plane(*plane) p3 = p3.project_plane(*plane) e1 = p1 - p3 e2 = p2 - p3 th = dpv.angle_between(e1,e2) th = numpy.pi if th < 0.0001 else th cr = dpv.distance(p1,p2)/(2*numpy.sin(th)) cp = e2.copy().scale_u(e1.magnitude2())-e1.copy().scale_u(e2.magnitude2()) cp = cp.cross(e1.cross(e2)).scale_u(1.0/(2.0*(e1.cross(e2).magnitude2()))) return cp+p3,cr
def _find_node_cone(self,o,p,e): ca = dpr.deg(dpv.angle_from_xaxis_xy(dpv.v1_v2(o,p).normalize())) #best,margin = None,dpv.distance(o,p) best,margin = None,100000000000000000 for ndx in range(self.nodecount): nd = self.nodes[ndx] tn = dpv.v1_v2(o,nd.p).normalize() npa = dpr.deg(dpv.angle_from_xaxis_xy(tn)) if adist(ca,npa) < e: ndd = dpv.distance(o,nd.p) if ndd < margin: best = ndx margin = ndd return best
def locally_delaunay_edge(self,u,v): v1,v2 = self.points.get_points(u,v) cc = dpv.midpoint(v1,v2) cr = dpv.distance(cc,v1) polyxs = self.eg_poly_lookup[self.eg_lookup[(u,v)]] polyps = [self.get_polygon_points(px) for px in polyxs] for polyp in polyps: ebps,ibs = polyp for ep in ebps: if ep.near(v1) or ep.near(v2):continue if dpr.inside_circle(ep,cc,cr):return False for ibps in ibs: for ip in ibps: if ip.near(v1) or ip.near(v2):continue if dpr.inside_circle(ip,cc,cr):return False return True
def clean_polygon(eb,ibs): clean = False neb = eb[:] #nibs = [ib[:] for ib in ibs] flag = False while not clean: icnt = len(ibs) nibs = [] if icnt == 0:clean = True else: for x in range(icnt): ib = ibs[x] isect = dpr.concaves_intersect(neb,ib) ins = dpr.inconcave_xy(ib[0],neb) if isect: neb = dtl.polygon_difference((neb,()),(ib,()))[0] print('polygon hole intersects boundary',x) ax = dtl.plot_axes() ax = dtl.plot_polygon_full((neb,()),ax) plt.show() flag = True break elif ins:nibs.append(ib) else:print('polygon hole found outside of boundary',x) print('wtf',x,icnt) if x == icnt - 1:clean = True if flag: tns = [dpv.distance(neb[t-1],neb[t]) for t in range(len(neb))] print('exit CLEANPOLYGON',tns) ax = dtl.plot_axes() ax = dtl.plot_polygon_full((neb,nibs),ax) plt.show() return neb,nibs
def should_shaft(self,plans,rmplan): rps,eps,ips,sps = plans sdist = 1000.0 rpos = dpv.vector(rmplan[1]['x'],rmplan[1]['y'],0) for sp in sps: spos = sp[1]['p'] sd = dpv.distance(spos,rpos) if sd < sdist:sdist = sd splan = None newl,neww = rmplan[1]['l'],rmplan[1]['w'] if sdist > self.min_shaft_distance and newl >= 16 and neww >= 18: shx,shy = rmplan[1]['x'],rmplan[1]['y'] shl = 8 shw = 10 sps = dpv.vector(shx,shy,0) gap = (dpv.zero(),shl,shw) rmplan[1]['shafted'] = True rmplan[1]['fgap'] = gap rmplan[1]['cgap'] = gap splan = ((),{'p':sps,'l':gap[1],'w':gap[2]}) return splan
def should_shaft(self, plans, rmplan): rps, eps, ips, sps = plans sdist = 1000.0 rpos = dpv.vector(rmplan[1]['x'], rmplan[1]['y'], 0) for sp in sps: spos = sp[1]['p'] sd = dpv.distance(spos, rpos) if sd < sdist: sdist = sd splan = None newl, neww = rmplan[1]['l'], rmplan[1]['w'] if sdist > self.min_shaft_distance and newl >= 16 and neww >= 18: shx, shy = rmplan[1]['x'], rmplan[1]['y'] shl = 8 shw = 10 sps = dpv.vector(shx, shy, 0) gap = (dpv.zero(), shl, shw) rmplan[1]['shafted'] = True rmplan[1]['fgap'] = gap rmplan[1]['cgap'] = gap splan = ((), {'p': sps, 'l': gap[1], 'w': gap[2]}) return splan
def calculate_count(self, v1, v2): ds = dpv.distance(v1, v2) seglen = 3 self.lastsegcnt = int(ds / seglen) return self.lastsegcnt
def search_offset_random(self,p1,p2): return (2.0*random.random()-1.0)*dpv.distance(p1,p2)/8.0
def shortest_edge_tri(*tri): p1,p2,p3 = tri e1 = dpv.distance(p1,p2) e2 = dpv.distance(p2,p3) e3 = dpv.distance(p3,p1) return min((e1,e2,e3))
def edge_lengths(*poly): elengs = [] for x in range(len(poly)): p1,p2 = poly[x-1],poly[x] elengs.append(dpv.distance(p1,p2)) return elengs
def shortest_edge_tri(*tri): p1, p2, p3 = tri e1 = dpv.distance(p1, p2) e2 = dpv.distance(p2, p3) e3 = dpv.distance(p3, p1) return min((e1, e2, e3))
def edge_lengths(*poly): elengs = [] for x in range(len(poly)): p1, p2 = poly[x - 1], poly[x] elengs.append(dpv.distance(p1, p2)) return elengs
def inside_circle(pt,center,radius,plane): pt = pt.project_plane(*plane) center = center.project_plane(*plane) ins = not dpv.distance(pt,center) > radius return ins
def closer(p,r,l): if dpv.distance(p,r) < dpv.distance(p,l):return r else:return l
def inside(x1,x2,x3): d12 = dpv.distance(x1,x2) d13 = dpv.distance(x1,x3) d23 = dpv.distance(x2,x3) if d13 <= d12 and d23 <= d12:return True else:return False
def connect_end(lp,lpt): d1,d2 = dpv.distance(lp[0],lpt),dpv.distance(lp[-1],lpt) if d1 < d2:return lp[:] else:return lp[::-1]
def _find_road_points(self,tip,le,ne): # create the shortest line segment from el1 to el2 def tiptail(el1,el2): d1 = dpv.distance(el1[ 0],el2[ 0]) d2 = dpv.distance(el1[ 0],el2[-1]) d3 = dpv.distance(el1[-1],el2[ 0]) d4 = dpv.distance(el1[-1],el2[-1]) md = min(d1,d2,d3,d4) if md == d1:return el1[ 0],el2[ 0] elif md == d2:return el1[ 0],el2[-1] elif md == d3:return el1[-1],el2[ 0] elif md == d4:return el1[-1],el2[-1] def closer(p,r,l): if dpv.distance(p,r) < dpv.distance(p,l):return r else:return l '''# ax = dtl.plot_axes_xy() ax = dtl.plot_point_xy(tip,ax) ax = dtl.plot_edges_xy(le.rpts,ax) ax = dtl.plot_edges_xy(ne.rpts,ax) s1,s2 = tiptail(le.rpts,ne.rpts) ax = dtl.plot_edges_xy([s1,s2],ax,lw = 5.0) ax = dtl.plot_edges_xy([tip,closer(tip,ne.rbpts[0],ne.rbpts[-1])],ax) ax = dtl.plot_edges_xy([tip,closer(tip,ne.lbpts[0],ne.lbpts[-1])],ax) plt.show() '''# '''# this function is verrrrry sloppy.... rewrite it.... '''# def same_side(lp): lp0d = dpv.distance(lp[ 0],tip) lp1d = dpv.distance(lp[-1],tip) lpt = lp[0] if lp0d < lp1d else lp[-1] s1,s2 = tiptail(le.rpts,ne.rpts) segsect = dpr.segments_intersect_noncolinear(s1,s2,lpt,tip) if not segsect:return lpt def connect_end(lp,lpt): d1,d2 = dpv.distance(lp[0],lpt),dpv.distance(lp[-1],lpt) if d1 < d2:return lp[:] else:return lp[::-1] if le is ne: if tip in le.rbpts:return connect_end(ne.lbpts,tip) else:return connect_end(ne.rbpts,tip) else: lrpt = same_side(ne.rbpts) llpt = same_side(ne.lbpts) if lrpt is None and llpt is None: lsd = dpv.distance(tip,ne.lbpts[ 0]) led = dpv.distance(tip,ne.lbpts[-1]) rsd = dpv.distance(tip,ne.rbpts[ 0]) red = dpv.distance(tip,ne.rbpts[-1]) sxs = dpr.order_ascending([lsd,led,rsd,red]) nelooppts = None for sx in sxs: if sx == 0 and not tip in ne.lbpts:nelooppts = ne.lbpts[:] elif sx == 1 and not tip in ne.lbpts:nelooppts = ne.lbpts[:-1] elif sx == 2 and not tip in ne.rbpts:nelooppts = ne.rbpts[:] elif sx == 3 and not tip in ne.rbpts:nelooppts = ne.rbpts[:-1] if not nelooppts is None:break return nelooppts if not lrpt is None:return connect_end(ne.rbpts,lrpt) else:return connect_end(ne.lbpts,llpt)