Exemplo n.º 1
0
static inline void
edges_start_or_continue (cairo_bo_edge_t	*left,
			 cairo_bo_edge_t	*right,
			 int			 top,
			 cairo_polygon_t	*polygon)
{
    assert (right->deferred.other == NULL);

    if (left->deferred.other == right)
	return;

    if (left->deferred.other != NULL) {
	if (right != NULL && edges_colinear (left->deferred.other, right)) {
	    cairo_bo_edge_t *old = left->deferred.other;

	    /* continuation on right, extend right to cover both */
	    assert (old->deferred.other == NULL);
	    assert (old->edge.line.p2.y > old->edge.line.p1.y);

	    if (old->edge.line.p1.y < right->edge.line.p1.y)
		right->edge.line.p1 = old->edge.line.p1;
	    if (old->edge.line.p2.y > right->edge.line.p2.y)
		right->edge.line.p2 = old->edge.line.p2;
	    left->deferred.other = right;
	    return;
	}

	edges_end (left, top, polygon);
    }

    if (right != NULL && ! edges_colinear (left, right)) {
	left->deferred.top = top;
	left->deferred.other = right;
    }
}
Exemplo n.º 2
0
static inline void
active_edges (cairo_bo_edge_t		*left,
	      int32_t			 top,
	      cairo_polygon_t	        *polygon)
{
	cairo_bo_edge_t *right;
	int winding[2] = {0, 0};

	/* Yes, this is naive. Consider this a placeholder. */

	while (left != NULL) {
	    assert (is_zero (winding));

	    do {
		winding[left->a_or_b] += left->edge.dir;
		if (! is_zero (winding))
		    break;

		if unlikely ((left->deferred.other))
		    edges_end (left, top, polygon);

		left = left->next;
		if (! left)
		    return;
	    } while (1);

	    right = left->next;
	    do {
		if unlikely ((right->deferred.other))
		    edges_end (right, top, polygon);

		winding[right->a_or_b] += right->edge.dir;
		if (is_zero (winding)) {
		    if (right->next == NULL ||
			! edges_colinear (right, right->next))
			break;
		}

		right = right->next;
	    } while (1);

	    edges_start_or_continue (left, right, top, polygon);

	    left = right->next;
	}
}
Exemplo n.º 3
0
bool Boundary::contour_is_complete (contour_iterator cit) const
{
    edge_iterator eit = edges_begin (cit);
    edge_iterator end = edges_end (cit);
    for (; eit != end; ++eit)
        if (!edge_has_successor (eit))
            return false;
    return true;
}
Exemplo n.º 4
0
void Boundary::reverse_contour (Boundary::contour_iterator cit) {
    edge_iterator eit     = edges_begin (cit);
    edge_iterator eit_end = edges_end (cit);
    for (; eit != eit_end; ++eit) {
        edge_t &E = edge (eit);
        std::swap (E.prev, E.next);
        std::swap (E.vert0, E.vert1);
    }
}
Exemplo n.º 5
0
void Boundary::fix_contours (bool silent) {
    assert_boundary (*this);
    if (!silent)
        std::cerr << "fix_contours";
    int deg_edges = 0;
    int deg_spikes = 0;
    std::vector <int> deg_con_indices;
    Boundary::contour_iterator cit = contours_begin ();
    Boundary::contour_iterator cit_end = contours_end ();
    Boundary::edge_iterator eit, eit_end;
    while (cit != cit_end) {
        bool fixed_something = false;
        eit = edges_begin (cit);
        eit_end = edges_end (cit);
        // remove spikes with exterior angle = pi
        while (eit != eit_end) {
            edge_iterator eit_next = eit;
            ++eit_next;

            vec_t d = edge_vertex1 (eit_next);
            d -= edge_vertex0 (eit);

            if (d.norm () < VERTEX_MERGE_TOLERANCE) {
                if (is_self_referential (eit)) {
                    // further processing is dangerous
                    goto deg_contour;
                }
                // remove spike.  the norm-zero edge created by this
                // operation is removed later
                eit = remove_vertex1 (eit);
                ++deg_spikes;
                --eit;
                // remove_vertex1 could have removed our end
                eit_end = edges_end (cit);
                fixed_something = true;
            } else {
                eit = eit_next;
            }
        }
        eit = edges_begin (cit);
        // remove norm-zero edges
        while (eit != eit_end) {
            double len = edge_length (eit);
            if (len < VERTEX_MERGE_TOLERANCE) {
                if (is_self_referential (eit)) {
                    // further processing is dangerous
                    goto deg_contour;
                }
                ++deg_edges;
                eit = remove_vertex1 (eit);
                // remove_vertex1 could have removed our end
                eit_end = edges_end (cit);
                fixed_something = true;
            } else {
                ++eit;
            }
        }

        if (!fixed_something)
            ++cit;
        continue;

    deg_contour:
        // current contour has been reduced to or was a single-vertex
        // contour.  we mark it for later removal.
        deg_con_indices.push_back (cit - contours_begin ());
        ++cit;
    }
    int deg_contours = (int)deg_con_indices.size ();
    // remove degenerate contours
    {
        std::vector <int>::reverse_iterator it;
        it = deg_con_indices.rbegin ();
        for (; it != deg_con_indices.rend (); ++it) {
            erase_contour_by_index (*it);
        }
    }

    // final "status report"
    if (!silent) {
        std::cerr << "\n"
                  << std::setw (4) << deg_contours << " deg. contours (removed)\n"
                  << std::setw (4) << deg_spikes << " deg. spikes (removed)\n"
                  << std::setw (4) << deg_edges << " deg. edges (removed)\n";
    }
    assert_boundary (*this);
}
Exemplo n.º 6
0
static cairo_status_t
intersection_sweep (cairo_bo_event_t   **start_events,
		    int			 num_events,
		    cairo_polygon_t	*polygon)
{
    cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
    cairo_bo_event_queue_t event_queue;
    cairo_bo_sweep_line_t sweep_line;
    cairo_bo_event_t *event;
    cairo_bo_edge_t *left, *right;
    cairo_bo_edge_t *e1, *e2;

    _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
    _cairo_bo_sweep_line_init (&sweep_line);

    while ((event = _cairo_bo_event_dequeue (&event_queue))) {
	if (event->point.y.ordinate != sweep_line.current_y) {
	    active_edges (sweep_line.head,
			  sweep_line.current_y,
			  polygon);
	    sweep_line.current_y = event->point.y.ordinate;
	}

	switch (event->type) {
	case CAIRO_BO_EVENT_TYPE_START:
	    e1 = &((cairo_bo_start_event_t *) event)->edge;

	    status = sweep_line_insert (&sweep_line, e1);
	    if (unlikely (status))
		goto unwind;

	    status = event_queue_insert_stop (&event_queue, e1);
	    if (unlikely (status))
		goto unwind;

	    left = e1->prev;
	    right = e1->next;

	    if (left != NULL) {
		status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1);
		if (unlikely (status))
		    goto unwind;
	    }

	    if (right != NULL) {
		status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
		if (unlikely (status))
		    goto unwind;
	    }

	    break;

	case CAIRO_BO_EVENT_TYPE_STOP:
	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
	    _cairo_bo_event_queue_delete (&event_queue, event);

	    if (e1->deferred.other)
		edges_end (e1, sweep_line.current_y, polygon);

	    left = e1->prev;
	    right = e1->next;

	    _cairo_bo_sweep_line_delete (&sweep_line, e1);

	    if (left != NULL && right != NULL) {
		status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
		if (unlikely (status))
		    goto unwind;
	    }

	    break;

	case CAIRO_BO_EVENT_TYPE_INTERSECTION:
	    e1 = ((cairo_bo_queue_event_t *) event)->e1;
	    e2 = ((cairo_bo_queue_event_t *) event)->e2;
	    _cairo_bo_event_queue_delete (&event_queue, event);

	    /* skip this intersection if its edges are not adjacent */
	    if (e2 != e1->next)
		break;

	    if (e1->deferred.other)
		edges_end (e1, sweep_line.current_y, polygon);
	    if (e2->deferred.other)
		edges_end (e2, sweep_line.current_y, polygon);

	    left = e1->prev;
	    right = e2->next;

	    _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);

	    /* after the swap e2 is left of e1 */

	    if (left != NULL) {
		status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2);
		if (unlikely (status))
		    goto unwind;
	    }

	    if (right != NULL) {
		status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
		if (unlikely (status))
		    goto unwind;
	    }

	    break;
	}
    }

 unwind:
    _cairo_bo_event_queue_fini (&event_queue);

    return status;
}
Exemplo n.º 7
0
struct Edge* find_MST_parallel_star(Graph g){
    omp_set_num_threads(THREADS);
    int n = get_num_nodes(g);
    //store the edge index of the min weight edge incident on node i
    struct Edge* min_edges = new struct Edge[n];
    struct set *components = new struct set[n];

    struct Edge* mst_edges = new struct Edge[n];

    bool *coin_flips = new bool[n];
    //bool not_one_component = true;
    //keeps track of which tails have been contracted
    bool *is_contracted = new bool[n];
    
    //bool not_one_component = true;

    //this is a hacky way to accommodate the fact that we look at every edge
    //even though we're contracting
    bool is_first_passes[n];
    //loop guard - did the graph get smaller - only needs to be set by
    //at least one thread so it should work in the parallel version
    bool can_be_contracted = true;

    #pragma omp parallel for schedule(static)
    for(int i = 0; i < n; i++){
        components[i].parent = i;
        components[i].rank = 0;
        is_first_passes[i] = true;
    }

    double startTimeFind, endTimeFind;
    double findTotal = 0.0;
    double startTimeContract, endTimeContract;
    double contractTotal = 0.0;
    //continue looping until there's only 1 component
    //in the case of a disconnected graph, until num_components doesn't change
    //TODO is it better to have one condition here and not have to deal with
    //not_one_component (you would go one extra iteration but it could be worth 
    //it instad of having to loop through the components list every iteration -
    //but one iteration could be just as expensive so we'll have to see)
    while(can_be_contracted){
        startTimeFind = CycleTimer::currentSeconds();
        #pragma omp parallel for schedule(dynamic, CHUNKSIZE)
        for(int j = 0; j < n; j++){
            if(find_parallel(components, j) == j){
            //find minimum weight edge out of each componenet
                for(int i = 0; i < n; i++){
                    int set1 = find_parallel(components, i);
                    if(set1 == j){
                        const Vertex* start = edges_begin(g, i);
                        const Vertex* end = edges_end(g, i);
                        int weight_offset = -1;
                        for(const Vertex* v = start; v < end; v++){
                            weight_offset++;
                            //get representative nodes 
                            int set2 = find_parallel(components, *v);
                            //this edge has already been contracted (endpoints in same component)
                            if(set1 != set2){
                                Edge e;
                                e.src = i;
                                e.dest = *v;
                                e.weight = g->weights[g->offsets[i] + weight_offset];
                                if(is_first_passes[set1]){
                                    min_edges[set1] = e; 
                                    is_first_passes[set1] = false;
                                }
                                else if (min_edges[set1].weight > e.weight)
                                    min_edges[set1] = e;
                            }
                        }
                    }
                }
            }
        }

        endTimeFind = CycleTimer::currentSeconds();
        findTotal += (endTimeFind - startTimeFind);

        startTimeContract = CycleTimer::currentSeconds();
        //TODO: need to rewrite union find so that it always contract the edge that we want
        //it to - this is necessary in star contraction so we contract into the HEAD        
        //determine which vertices will be star centers and which are satellites
        //we make 0 mean you are a satellite (false) and 1 mean you are a star center (true)
        #pragma omp parallel for schedule(static)
        for(int i = 0; i < n; i++){
            coin_flips[i] = ((rand() % 2) == 1);
        }

        //do this so we can see if any thread sets to true meaning something got contracted
        can_be_contracted = false;
        //star contraction - we'll say 1 is HEADS and 0 is TAILS
        #pragma omp parallel for schedule(dynamic, CHUNKSIZE) 
        for(int i = 0; i < n; i++){
            int src = min_edges[i].src;
            int dest = min_edges[i].dest;

            int root1 = find_parallel(components, src);
            int root2 = find_parallel(components, dest);
            if(root1 == root2){
                continue;
            }
            can_be_contracted = true;
            //you wouldn't contract in case of both heads or both tails
            if((coin_flips[root1] == coin_flips[root2])){
                continue;
            }
            //try to contract, but if you fail, that means someone has contracted already
            //I think this should be correct by how CAS works
            //mark the tail as having been contracted
            if(coin_flips[root1]){
                if(!__sync_bool_compare_and_swap(&is_contracted[root2],false,true))
                    continue;
            }
            else{
                if(!__sync_bool_compare_and_swap(&is_contracted[root1],false,true))
                    continue;
            }
            if(coin_flips[root1]){
                union_parallel(components, root2, root1);
                mst_edges[root2] = min_edges[i];
            }
            else{
                union_parallel(components, root1, root2);
                mst_edges[root1] = min_edges[i];
            }
        }

        #pragma omp parallel for schedule(static)
        for(int i = 0; i < n; i++){
            is_first_passes[i] = true;
            is_contracted[i] = false;
        }
        endTimeContract = CycleTimer::currentSeconds();
        contractTotal += (endTimeContract - startTimeContract);
    }

/*    for(int i = 0; i < n; i++){
        if(mst_edges[i].src == 0 && mst_edges[i].dest == 0)
            continue;
        if(mst_edges[i].src < 0 || mst_edges[i].src > n || mst_edges[i].dest < 0 || mst_edges[i].dest > n)
            continue;
        printf("%d, %d\n", mst_edges[i].src, mst_edges[i].dest);
    }
  */  
    printf("find time parallel comp star: %.20f\n", findTotal);
    printf("contract time parallel comp star: %.20f\n", contractTotal);
    delete[] min_edges;
    delete[] components;
    return mst_edges;
}