diff -urN rt_v46/Makefile rt_v47/Makefile --- rt_v46/Makefile 2018-05-07 22:55:30.000000000 +0900 +++ rt_v47/Makefile 2018-06-08 01:48:57.000000000 +0900 @@ -1,7 +1,7 @@ CC = gcc CFLAGS += -Wall LIBS = -lm -lpthread -OBJS = img.o dat.o val.o sock.o lstx.o ax.o cylx.o fcx.o vecs.o line.o v.o mt.o ut.o +OBJS = area.o img.o dat.o val.o sock.o lstx.o ax.o cylx.o fcx.o vecs.o line.o v.o mt.o ut.o all: cross rt diff -urN rt_v46/and.yaml rt_v47/and.yaml --- rt_v46/and.yaml 1970-01-01 09:00:00.000000000 +0900 +++ rt_v47/and.yaml 2018-06-08 01:42:51.000000000 +0900 @@ -0,0 +1,40 @@ +defs: + rtd_A: { base: 0.1, diff: 0, reflect: 0.5, reflact: 0.5, density: 2 } + mov4: IMG_3999_4.mov + +big_ball: +- kind: ball + rtd: { diff: 0.3 } + maps: + - fn: '*mov4' + fn_r: '*mov4' + t2m: [ ax.zoom_all(2), ax.rot_x(90) ] + - fn: '*mov4' + fn_r: '*mov4' + t2m: [ ax.zoom_all(2), ax.rot_x(90), ax.rot_z(180) ] + m2g: [ ax.zoom_all(1000) ] + +all: +- kind: export + export: big_ball + +- kind: and + args: + - kind: ball + rtd: '*rtd_A' + - kind: cube + rtd: '*rtd_A' + m2g: [ 'ax.zoom_all(0.8)' ] + m2g: [ 'ax.zoom_all(30)', 'ax.slide_x(-30)' ] + +- kind: and + args: + - kind: cube + rtd: '*rtd_A' + m2g: [ 'ax.zoom_all(0.8)' ] + - kind: ball + not: True + rtd: '*rtd_A' + m2g: [ 'ax.zoom_all(30)', 'ax.slide_x(30)' ] + +# EOF diff -urN rt_v46/area.c rt_v47/area.c --- rt_v46/area.c 1970-01-01 09:00:00.000000000 +0900 +++ rt_v47/area.c 2018-06-08 01:48:48.000000000 +0900 @@ -0,0 +1,150 @@ +#include "area.h" + +void +area_init(struct area *a, int v) +{ + a->v = v; + a->p = NULL; +} + +static struct node * +node_new(double t, void *d, struct node *next) +{ + struct node *p = malloc( sizeof(*p) ); + + p->t = t; + p->d = d; + p->next = next; + return p; +} + +void +area_ins(struct area *a, double t, void *d) +{ + struct node **pp = &a->p, *p = *pp; + + while( p && p->t <= t ){ + pp = &p->next; + p = *pp; + } + *pp = node_new(t, d, p); +} + +void +area_free(struct area *a) +{ + struct node *p = a->p, *next; + for(; p; p=next){ + next = p->next; + free(p); + } + a->p = NULL; +} + +int +area_val(struct area *a, double t) +{ + int v = a->v; + struct node *p = a->p; + + while( p && p->t <= t ){ + v = !v; + p = p->next; + } + return v; +} + +void +area_and(struct area *a, struct area *b, struct area *r) +{ + struct node *ap = a->p, *bp = b->p; + + area_init(r, a->v && b->v); + while( ap || bp ){ + if( !bp || (ap && ap->t < bp->t) ){ + if( area_val(b, ap->t) ){ + area_ins(r, ap->t, ap->d); + } + ap = ap->next; + }else{ + if( area_val(a, bp->t) ){ + area_ins(r, bp->t, bp->d); + } + bp = bp->next; + } + } +} + +void +area_or(struct area *a, struct area *b, struct area *r) +{ + struct node *ap = a->p, *bp = b->p; + + area_init(r, a->v || b->v); + while( ap || bp ){ + if( !bp || (ap && ap->t < bp->t) ){ + if( !area_val(b, ap->t) ){ + area_ins(r, ap->t, ap->d); + } + ap = ap->next; + }else{ + if( !area_val(a, bp->t) ){ + area_ins(r, bp->t, bp->d); + } + bp = bp->next; + } + } +} + +void +area_not(struct area *a, struct area *r) +{ + struct node *p = a->p; + + area_init(r, !a->v); + while(p){ + area_ins(r, p->t, p->d); + p = p->next; + } +} + +struct node * +area_has_d(struct area *a, void *d) +{ + struct node *p = a->p; + + while(p){ + if(p->d == d){ /* address */ + return p; + } + p = p->next; + } + return NULL; +} + +int +area_is_all(struct area *a, int v) +{ + return a->v == v && !a->p; +} + +void +area_show(struct area *a) +{ + struct node *p = a->p; + int v = a->v; + + if(!p){ + fprintf(stderr, "all %d\n", v); + return; + } + + while(p){ + fprintf(stderr, "%s(%f %p)", v ? "###" : "...", p->t, p->d); + p = p->next; + v = !v; + } + fprintf(stderr, "%s\n", v ? "###" : "..."); +} + +/* EOF */ diff -urN rt_v46/area.h rt_v47/area.h --- rt_v46/area.h 1970-01-01 09:00:00.000000000 +0900 +++ rt_v47/area.h 2018-06-08 01:48:54.000000000 +0900 @@ -0,0 +1,30 @@ +#ifndef __AREA_H__ +#define __AREA_H__ 1 + +#include +#include + +struct node{ + double t; + void *d; + struct node *next; +}; + +struct area{ + int v; + struct node *p; +}; + +void area_init(struct area *a, int v); +void area_ins(struct area *a, double t, void *d); +void area_free(struct area *a); +int area_val(struct area *a, double t); +void area_and(struct area *a, struct area *b, struct area *r); +void area_or(struct area *a, struct area *b, struct area *r); +void area_not(struct area *a, struct area *r); + +struct node *area_has_d(struct area *a, void *d); +void area_show(struct area *a); +int area_is_all(struct area *a, int v); + +#endif diff -urN rt_v46/cross.c rt_v47/cross.c --- rt_v46/cross.c 2018-05-19 14:02:39.000000000 +0900 +++ rt_v47/cross.c 2018-06-08 01:37:40.000000000 +0900 @@ -11,6 +11,12 @@ } pz = ret->l.p[2]; t = -pz / vz; + + if(ret->use_ts_only){ + ret->ts[ ret->ts_n++ ] = t; + return ret->ts_n; + } + if(t <= 0){ return 0; } @@ -24,6 +30,11 @@ if( !plane_z0(ret) ){ return 0; } + + if(ret->use_ts_only){ + return ret->ts_n; + } + line_on_line_p(&ret->l, ret->t, ret->p); return xy_cond_f( ret->p[0], ret->p[1] ); } @@ -76,6 +87,19 @@ c = dot( l->p, l->p ) - 1; n = quadratic_formula(a, b, c, ts); + + if(ret->use_ts_only){ + ret->ts_n = 0; + if(eq_d){ + return ret->ts_n; + } + for(i=0; its[ ret->ts_n++ ] = ts[i]; + } + ret->ts_n = ret->ts_n < 2 ? 0 : 2; /* ! */ + return ret->ts_n; + } + if(n == 0){ return 0; } @@ -121,6 +145,22 @@ c = px*px + py*py - 1; n = quadratic_formula(a, b, c, ts); + + if(ret->use_ts_only){ + ret->ts_n = 0; + if(eq_d){ + return ret->ts_n; + } + for(i=0; ip); + if( fabs(ret->p[2]) < 1 ){ + ret->ts[ ret->ts_n++ ] = ts[i]; + } + } + ret->ts_n = ret->ts_n < 2 ? 0 : 2; /* ! */ + return ret->ts_n; + } + if(n == 0){ return 0; } @@ -179,6 +219,22 @@ c = px*px + py*py - pz*pz + 2*pz - 1; n = quadratic_formula(a, b, c, ts); + + if(ret->use_ts_only){ + ret->ts_n = 0; + if(eq_d){ + return ret->ts_n; + } + for(i=0; ip); + if( 0p[2] && ret->p[2]<1 ){ + ret->ts[ ret->ts_n++ ] = ts[i]; + } + } + ret->ts_n = ret->ts_n < 2 ? 0 : 2; /* ! */ + return ret->ts_n; + } + if(n == 0){ return 0; } @@ -220,6 +276,10 @@ int cross_cross_one(int kind_idx, struct lstx *l2g, int eq_d, struct line *l_g, struct cross_ret *ret) { + if(ret->use_ts_only){ + ret->ts_n = 0; + } + switch(kind_idx){ case KIND_SQUARE: case KIND_CIRCLE: @@ -253,7 +313,7 @@ } void -cross_get_nv(int kind_idx, struct lstx *l2g, struct line *l_g, struct cross_ret *ret) +cross_get_nv(int kind_idx, struct lstx *l2g, struct line *l_g, int rev, struct cross_ret *ret) { double nv[3]; struct line l_nv; @@ -287,6 +347,9 @@ break; } + if(rev){ + v_neg(nv, nv); + } line_new(&l_nv, ret->p, nv); lstx_tr_line(l2g, L2G, &l_nv, &ret->l_nv_g); @@ -295,6 +358,139 @@ ret->ang_nv_eyev = dot( ret->nv, ret->eyev ); } +static void +my_area_ins(struct area *a, double t, struct cross_ret *ret) +{ + int sz = sizeof(*ret); + void *d = malloc(sz); + memcpy(d, ret, sz); + area_ins(a, t, d); +} + +static void +my_area_free(struct area *a, struct area *without) +{ + struct node *p = a->p; + while(p){ + if(p->d && ( !without || !area_has_d(without, p->d) ) ){ + free(p->d); + p->d = NULL; + } + p = p->next; + } + area_free(a); + +} + +static void +my_area_not(struct area *a) +{ + struct area r; + area_not(a, &r); + my_area_free(a, &r); + *a = r; +} + +static int +my_area_and(struct area *area, struct area *a) +{ + struct area r; + + area_and(area, a, &r); + my_area_free(area, &r); + my_area_free(a, &r); + *area = r; + return area_is_all(area, 0); +} + +static int +my_area_sel(struct area *a, struct cross_ret *ret) +{ + struct node *p = a->p; + + while(p && p->t <= 0){ + p = p->next; + } + if(p){ + memcpy(ret, p->d, sizeof(*ret)); + line_on_line_p(&ret->l, ret->t, ret->p); /* ! */ + } + my_area_free(a, NULL); + return p ? 1 : 0; +} + +static int +is_plane(int kind) +{ + return kind == KIND_SQUARE || kind == KIND_CIRCLE || kind == KIND_TRIANGLE; +} + +static int +cross_and(struct line *l_g, int prev_idx, struct data *data, int p_i, struct data_one *pd, struct cross_ret *ret) +{ + int i, j, n; + struct area area; + + area_init(&area, 1); /* for and */ + + for(i=0; ichildren.n; i++){ + struct cross_ret ret_; + int id = pd->children.lst[i]; + struct area a; + struct data_one *d; + int is_pl; + + for(j=0; jn; j++){ + if(data->lst[j].id == id){ + break; + } + } + if(j >= data->n){ + // err... + } + d = &data->lst[j]; + is_pl = is_plane(d->kind); + + ret_.use_ts_only = 1; + + n = cross_cross_one( d->kind, &d->l2g, prev_idx == j, l_g, &ret_ ); + + if( n == 0 && ( is_pl || !d->not ) ){ + return 0; + } + ret_.idx = j; + + area_init(&a, 0); + + if(is_pl){ + cross_get_nv( d->kind, &d->l2g, l_g, 0, &ret_ ); + if(ret_.ang_nv_eyev > 0){ + area_init(&a, 1); + } + ret_.t = ret_.ts[0]; + my_area_ins(&a, ret_.ts[0], &ret_); + }else if(n == 0){ /* && d->not */ + area_init(&a, 1); /* all */ + }else{ + int ii; + for(ii=0; ii<2; ii++){ + struct cross_ret r; + r = ret_; + r.t = ret_.ts[ii]; + my_area_ins(&a, r.t, &r); + } + if(d->not){ + my_area_not(&a); + } + } + if( my_area_and(&area, &a) ){ + break; + } + } + + return my_area_sel(&area, ret); +} + void cross_cross(struct line *l_g, int prev_idx, struct cross_ret *ret) { @@ -307,17 +503,27 @@ for(i=0; in; i++){ struct data_one *d = &data->lst[i]; - if( !cross_cross_one( d->kind, &d->l2g, prev_idx == i, l_g, &ret_ ) ){ + if(d->parent >= 0){ + continue; + } + + ret_.use_ts_only = 0; + ret_.idx = -1; + if(d->kind == KIND_AND){ + if( !cross_and( l_g, prev_idx, data, i, d, &ret_ ) ){ + continue; + } + }else if( !cross_cross_one( d->kind, &d->l2g, prev_idx == i, l_g, &ret_ ) ){ continue; } if( idx < 0 || ret_.t < ret->t ){ - idx = i; + idx = ret_.idx >= 0 ? ret_.idx : i; *ret = ret_; } } if( idx >= 0 ){ struct data_one *d = &data->lst[idx]; - cross_get_nv( d->kind, &d->l2g, l_g, ret ); + cross_get_nv( d->kind, &d->l2g, l_g, d->not, ret ); } ret->idx = idx; } diff -urN rt_v46/cross.h rt_v47/cross.h --- rt_v46/cross.h 2018-05-19 14:02:39.000000000 +0900 +++ rt_v47/cross.h 2018-06-08 00:23:05.000000000 +0900 @@ -2,6 +2,7 @@ #define __CROSS_H__ 1 #include "dat.h" +#include "area.h" struct cross_ret{ int idx; @@ -16,6 +17,10 @@ /* double diff; */ + /* for kind 'and' */ + int use_ts_only; + int ts_n; + double ts[2]; }; int plane_z0(struct cross_ret *ret); @@ -32,7 +37,7 @@ int cone_side(int eq_d, struct cross_ret *ret); int cross_cross_one(int kind_idx, struct lstx *l2g, int eq_d, struct line *l_g, struct cross_ret *ret); -void cross_get_nv(int kind_idx, struct lstx *l2g, struct line *l_g, struct cross_ret *ret); +void cross_get_nv(int kind_idx, struct lstx *l2g, struct line *l_g, int rev, struct cross_ret *ret); void cross_cross(struct line *l_g, int prev_idx, struct cross_ret *ret); diff -urN rt_v46/dat.c rt_v47/dat.c --- rt_v46/dat.c 2018-05-16 23:42:46.000000000 +0900 +++ rt_v47/dat.c 2018-06-07 23:39:31.000000000 +0900 @@ -86,6 +86,19 @@ } char * +unpack_ints(char *bp, struct ints *ints) +{ + int i; + + bp = COPY_FROM_BP(bp, ints->n); + ALLOC_LST(*ints, "ints"); + for(i=0; in; i++){ + bp = COPY_FROM_BP(bp, ints->lst[i]); + } + return bp; +} + +char * unpack_data_one(char *bp, struct data_one *d) { bp = COPY_FROM_BP(bp, d->kind); @@ -93,7 +106,11 @@ bp = COPY_FROM_BP_ARR(bp, d->def_col); bp = unpack_maps(bp, &d->maps); bp = unpack_rtd(bp, &d->rtd); + bp = COPY_FROM_BP(bp, d->not); + bp = COPY_FROM_BP(bp, d->id); + bp = COPY_FROM_BP(bp, d->parent); + bp = unpack_ints(bp, &d->children); return bp; } @@ -199,6 +216,7 @@ { free_lstx(&d->l2g); free_maps(&d->maps); + FREE_LST(d->children, "ints"); } void diff -urN rt_v46/dat.h rt_v47/dat.h --- rt_v46/dat.h 2018-05-16 23:42:46.000000000 +0900 +++ rt_v47/dat.h 2018-06-08 01:46:38.000000000 +0900 @@ -12,6 +12,8 @@ #define KIND_PIPE_SIDE 4 #define KIND_CONE_SIDE 5 +#define KIND_AND 6 + struct map{ struct lstx xyz2g; int fn; @@ -25,12 +27,22 @@ struct map *lst; }; +struct ints{ + int n; + int *lst; +}; + struct data_one{ int kind; struct lstx l2g; int def_col[3]; struct maps maps; struct rtd rtd; + int not; + + int id; + int parent; + struct ints children; }; struct data{ diff -urN rt_v46/dat.py rt_v47/dat.py --- rt_v46/dat.py 2018-06-05 22:38:30.000000000 +0900 +++ rt_v47/dat.py 2018-06-08 01:45:45.000000000 +0900 @@ -102,6 +102,17 @@ ydic = {} +def new_get_id(): + e = ut.Empty() + e.id = 0 + def f(): + id = e.id + e.id += 1 + return id + return f + +get_id = new_get_id() + def d_setup(d): # return lst [d] @@ -315,6 +326,14 @@ for k in def_rtd.keys(): if k not in rtd: rtd[k] = def_rtd.get(k) + + if 'not' not in d: + d['not'] = False + + d['id'] = get_id() + d['parent'] = -1 + d['children'] = [] + ### if kind == 'export' and 'export' in d: @@ -350,16 +369,31 @@ ### kinds = [ 'square', 'circle', 'triangle', 'ball', 'pipe_side', 'cone_side' ] + kinds += [ 'and' ] if not val.cli.has_prop('kinds'): val.cli.set_prop( 'kinds', '[str]', kinds ) kind = d.get('kind') if type(kind) != int: d['kind'] = kinds.index(kind) + ### + + if kind == 'and': + ds = [] + for d_ in d.get('args', []): + d_['m2g'] = d_.get('m2g', []) + d.get('l2g') + ds += d_setup(d_) + for d_ in ds: + d_['maps'] = d_.get('maps', []) + d.get('maps', []) + d_['parent'] = d.get('id') + d['children'].append( d_.get('id') ) + return [d] + ds + ### return [d] typ_map = '{xyz2g:lx,fn:i4,fn_r:i4,wh2xyz:lx,rep:(i4,i4)}' -typ_d = '{{kind:i4,l2g:lx,def_col:col,maps:[{}],rtd:rtd}}'.format(typ_map) +typ_ids = 'id:i4,parent:i4,children:[i4]' +typ_d = '{{kind:i4,l2g:lx,def_col:col,maps:[{}],rtd:rtd,not:bool,{}}}'.format(typ_map, typ_ids) typ_data = '[{}]'.format(typ_d) def setup(sec):