//判定线段与空间三角形相交,不包括交于边界和(部分)包含 int seg_triangle_inter2(const Line &l, const Plane &s) { return opposite_side(l.a, l.b, s) && opposite_side(s.a, s.b, Plane(l.a, l.b, s.c)) && opposite_side(s.b, s.c, Plane(l.a, l.b, s.a)) && opposite_side(s.c, s.a, Plane(l.a, l.b, s.b)); }
/* * There are two cases of single rotation possible: * 1) Right rotation (side = TNODE_LEFT) * [P] [L] * / \ / \ * [L] x1 => x2 [P] * / \ / \ * x2 x3 x3 x1 * * 2) Left rotation (side = TNODE_RIHGT) * [P] [R] * / \ / \ * x1 [R] => [P] x2 * / \ / \ * x3 x2 x1 x3 */ static void rotate_single(TtreeNode **target, int side) { TtreeNode *n; __rotate_single(target, side); n = (*target)->sides[opposite_side(side)]; /* * Recalculate balance factors of nodes after rotation. * Let X was a root node of rotated subtree and Y was its * child. After single rotation Y is new root of subtree and X is its child. * Y node may become either balanced or overweighted to the * same side it was but 1 level less. * X node scales at 1 level down and possibly it has new child, so * its balance should be recalculated too. If it still internal node and * its new parent was not overwaighted to the opposite to X side, * X is overweighted to the opposite to its new parent side, otherwise it's balanced. * If X is either half-leaf or leaf, balance racalculation is obvious. */ if (is_internal_node(n)) { n->bfc = (n->parent->bfc != side2bfc(side)) ? side2bfc(side) : 0; } else { n->bfc = !!(n->right) - !!(n->left); } (*target)->bfc += side2bfc(opposite_side(side)); TTREE_ASSERT((abs(n->bfc < 2) && (abs((*target)->bfc) < 2))); }
/* * There are two possible cases of double rotation: * 1) Left-right rotation: (side == TNODE_LEFT) * [P] [r] * / \ / \ * [L] x1 [L] [P] * / \ => / \ / \ * x2 [r] x2 x4 x3 x1 * / \ * x4 x3 * * 2) Right-left rotation: (side == TNODE_RIGHT) * [P] [l] * / \ / \ * x1 [R] [P] [R] * / \ => / \ / \ * [l] x2 x1 x3 x4 x2 * / \ * x3 x4 */ static void rotate_double(TtreeNode **target, int side) { int opside = opposite_side(side); TtreeNode *n = (*target)->sides[side]; __rotate_single(&n, opside); /* * Balance recalculation is very similar to recalculation after * simple single rotation. */ if (is_internal_node(n->sides[side])) { n->sides[side]->bfc = (n->bfc == side2bfc(opside)) ? side2bfc(side) : 0; } else { n->sides[side]->bfc = !!(n->sides[side]->right) - !!(n->sides[side]->left); } TTREE_ASSERT(abs(n->sides[side]->bfc) < 2); n = n->parent; __rotate_single(target, side); if (is_internal_node(n)) { n->bfc = ((*target)->bfc == side2bfc(side)) ? side2bfc(opside) : 0; } else { n->bfc = !!(n->right) - !!(n->left); } /* * new root node of subtree is always ideally balanced * after double rotation. */ TTREE_ASSERT(abs(n->bfc) < 2); (*target)->bfc = 0; }
/* * generic single rotation procedrue. * side = TNODE_LEFT - Right rotation * side = TNODE_RIGHT - Left rotation. * "target" will be set to the new root of rotated subtree. */ static void __rotate_single(TtreeNode **target, int side) { TtreeNode *p, *s; int opside = opposite_side(side); p = *target; TTREE_ASSERT(p != NULL); s = p->sides[side]; TTREE_ASSERT(s != NULL); tnode_set_side(s, tnode_get_side(p)); p->sides[side] = s->sides[opside]; s->sides[opside] = p; tnode_set_side(p, opside); s->parent = p->parent; p->parent = s; if (p->sides[side]) { p->sides[side]->parent = p; tnode_set_side(p->sides[side], side); } if (s->parent) { if (s->parent->sides[side] == p) s->parent->sides[side] = s; else s->parent->sides[opside] = s; } *target = s; }
void report_income(price_t income, std::ostream & os) { assert(income > 0); if (myabs(income - m_last_income) < 0.005) return; #ifndef PROFILING //printf("%u %c %.2f\n", m_last_timestamp, opposite_side(m_side), income); os << m_last_timestamp << ' ' << char_from_side(opposite_side(m_side)) << ' ' << income << '\n'; #endif m_last_income = income; }
//判线段在任意多边形内,顶点按顺时针或逆时针给出,与边界相交返回1 int inside_polygon(point l1,point l2,int n,point* p){ point t[MAXN],tt; int i,j,k=0; if (!inside_polygon(l1,n,p)||!inside_polygon(l2,n,p)) return 0; for (i=0;i<n;i++) if (opposite_side(l1,l2,p[i],p[(i+1)%n])&&opposite_side(p[i],p[(i+1)%n],l1,l2)) return 0; else if (dot_online_in(l1,p[i],p[(i+1)%n])) t[k++]=l1; else if (dot_online_in(l2,p[i],p[(i+1)%n])) t[k++]=l2; else if (dot_online_in(p[i],l1,l2)) t[k++]=p[i]; for (i=0;i<k;i++) for (j=i+1;j<k;j++){ tt.x=(t[i].x+t[j].x)/2; tt.y=(t[i].y+t[j].y)/2; if (!inside_polygon(tt,n,p)) return 0; } return 1; }
bool not_available(int target_size, std::ostream &os) { // if enough shares to (buy) sell if (m_shares < target_size) { if (m_last_income > 0) { #ifndef PROFILING os << m_last_timestamp << ' ' << char_from_side(opposite_side( m_side)) << " NA\n"; #endif m_last_income = -1; // not available } return true; } return false; }
//判定两线段相交,不包括端点和部分重合 bool seg_seg_inter(const Line &u, const Line &v) { return point_on_plane(u.a, Plane(u.b, v.a, v.b)) && opposite_side(u.a, u.b, v) && opposite_side(v.a, v.b, u); }
//判两线段相交,不包括端点和部分重合 int intersect_ex(line u,line v){ return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u); }
int intersect_ex(point u1,point u2,point v1,point v2){ return opposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2); }
static void rebalance(Ttree *ttree, TtreeNode **node, TtreeCursor *cursor) { int lh = left_heavy(*node); int sum = abs((*node)->bfc + (*node)->sides[opposite_side(lh)]->bfc); if (sum >= 2) { rotate_single(node, opposite_side(lh)); goto out; } rotate_double(node, opposite_side(lh)); /* * T-tree rotation rules difference from AVL rules in only one aspect. * After double rotation is done and a leaf became a new root node of * subtree and both its left and right childs are half-leafs. * If the new root node contains only one item, N - 1 items should * be moved into it from one of its childs. * (N is a number of items in selected child node). */ if ((tnode_num_keys(*node) == 1) && is_half_leaf((*node)->left) && is_half_leaf((*node)->right)) { TtreeNode *n; int offs, nkeys; /* * If right child contains more items than left, they will be moved * from the right child. Otherwise from the left one. */ if (tnode_num_keys((*node)->right) >= tnode_num_keys((*node)->left)) { /* * Right child was selected. So first N - 1 items will be copied * and inserted after parent's first item. */ n = (*node)->right; nkeys = tnode_num_keys(n); (*node)->keys[0] = (*node)->keys[(*node)->min_idx]; offs = 1; (*node)->min_idx = 0; (*node)->max_idx = nkeys - 1; if (!cursor) { goto no_cursor; } else if (cursor->tnode == n) { if (cursor->idx < n->max_idx) { cursor->tnode = *node; cursor->idx = (*node)->min_idx + (cursor->idx - n->min_idx + 1); } else { cursor->idx = first_tnode_idx(ttree); } } } else { /* * Left child was selected. So its N - 1 items * (starting after the min one) * will be copied and inserted before parent's single item. */ n = (*node)->left; nkeys = tnode_num_keys(n); (*node)->keys[ttree->keys_per_tnode - 1] = (*node)->keys[(*node)->min_idx]; (*node)->min_idx = offs = ttree->keys_per_tnode - nkeys; (*node)->max_idx = ttree->keys_per_tnode - 1; if (!cursor) { goto no_cursor; } else if (cursor->tnode == n) { if (cursor->idx > n->min_idx) { cursor->tnode = *node; cursor->idx = (*node)->min_idx + (cursor->idx - n->min_idx); } else { cursor->idx = first_tnode_idx(ttree); } } n->max_idx = n->min_idx++; } no_cursor: memcpy((*node)->keys + offs, n->keys + n->min_idx, sizeof(void *) * (nkeys - 1)); n->keys[first_tnode_idx(ttree)] = n->keys[n->max_idx]; n->min_idx = n->max_idx = first_tnode_idx(ttree); } out: if (ttree->root->parent) { ttree->root = *node; } }