Ejemplo n.º 1
0
int find_chains_from(Graph* graph, int start)
{
    Node *temp = graph->adj_list[start].list, *cur;
    EdgeList* edgelist = NULL;
    int chains = 0;

    //simple chains cannot begin from a degree two vertex
    if(graph->adj_list[start].edges == 2)
        return 0;

    //All simple chains from this vertex have been explored
    graph->vertex_list[start].visited = TRUE;


    //increment over the adjacent (nodes)vertices of the vertex with id "start"
    while(temp)
    {
        //if the adjacent vertex has not already been visited
        if(temp->vertex->visited == FALSE)
        {
            print_vertex(&graph->vertex_list[start], " -> ");
            //travel along the simple chain
            cur = temp;
            edgelist = &graph->adj_list[cur->vertex->id];
            while(1)
            {
                if(edgelist->edges == 2)
                {
                    cur->vertex->visited = TRUE;
                    print_vertex(cur->vertex, " -> ");

                    //Out of the two adjaxcent vertices choose the unvisited one.
                    //If both are visited then you are stuck in a cycle. Break out of it.
                    if(edgelist->list->vertex->visited)
                        if(edgelist->list->next->vertex->visited)
                        {
                            printf("<Detected a cycle!>\n");
                            break;
                        }
                        else
                            cur = edgelist->list->next;
                    else
                        cur = edgelist->list;
                    edgelist = &graph->adj_list[cur->vertex->id];
                }
                else
                {
                    print_vertex(cur->vertex, "");
                    chains++;
                    break;
                }
            }
            printf("\n");
        }

        temp = temp->next;
    }

    return chains;
}
Ejemplo n.º 2
0
/**
 * Do setup for triangle rasterization, then render the triangle.
 */
void
sp_setup_tri(struct setup_context *setup,
             const float (*v0)[4],
             const float (*v1)[4],
             const float (*v2)[4])
{
   float det;
   uint layer = 0;
   unsigned viewport_index = 0;
#if DEBUG_VERTS
   debug_printf("Setup triangle:\n");
   print_vertex(setup, v0);
   print_vertex(setup, v1);
   print_vertex(setup, v2);
#endif

   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
      return;
   
   det = calc_det(v0, v1, v2);
   /*
   debug_printf("%s\n", __FUNCTION__ );
   */

#if DEBUG_FRAGS
   setup->numFragsEmitted = 0;
   setup->numFragsWritten = 0;
#endif

   if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
      return;

   setup_tri_coefficients( setup );
   setup_tri_edges( setup );

   assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);

   setup->span.y = 0;
   setup->span.right[0] = 0;
   setup->span.right[1] = 0;
   /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */
   if (setup->softpipe->layer_slot > 0) {
      layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot];
      layer = MIN2(layer, setup->max_layer);
   }
   setup->quad[0].input.layer = layer;

   if (setup->softpipe->viewport_index_slot > 0) {
      unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
      viewport_index = sp_clamp_viewport_idx(*udata);
   }
   setup->quad[0].input.viewport_index = viewport_index;

   /*   init_constant_attribs( setup ); */

   if (setup->oneoverarea < 0.0) {
      /* emaj on left:
       */
      subtriangle(setup, &setup->emaj, &setup->ebot, setup->ebot.lines, viewport_index);
      subtriangle(setup, &setup->emaj, &setup->etop, setup->etop.lines, viewport_index);
   }
   else {
      /* emaj on right:
       */
      subtriangle(setup, &setup->ebot, &setup->emaj, setup->ebot.lines, viewport_index);
      subtriangle(setup, &setup->etop, &setup->emaj, setup->etop.lines, viewport_index);
   }

   flush_spans( setup );

   if (setup->softpipe->active_statistics_queries) {
      setup->softpipe->pipeline_statistics.c_primitives++;
   }

#if DEBUG_FRAGS
   printf("Tri: %u frags emitted, %u written\n",
          setup->numFragsEmitted,
          setup->numFragsWritten);
#endif
}
Ejemplo n.º 3
0
/**
 * Do setup for point rasterization, then render the point.
 * Round or square points...
 * XXX could optimize a lot for 1-pixel points.
 */
void
sp_setup_point(struct setup_context *setup,
               const float (*v0)[4])
{
   struct softpipe_context *softpipe = setup->softpipe;
   const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
   const int sizeAttr = setup->softpipe->psize_slot;
   const float size
      = sizeAttr > 0 ? v0[sizeAttr][0]
      : setup->softpipe->rasterizer->point_size;
   const float halfSize = 0.5F * size;
   const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
   const float x = v0[0][0];  /* Note: data[0] is always position */
   const float y = v0[0][1];
   const struct sp_setup_info *sinfo = &softpipe->setup_info;
   uint fragSlot;
   uint layer = 0;
   unsigned viewport_index = 0;
#if DEBUG_VERTS
   debug_printf("Setup point:\n");
   print_vertex(setup, v0);
#endif

   assert(sinfo->valid);

   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
      return;

   assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);

   if (setup->softpipe->layer_slot > 0) {
      layer = *(unsigned *)v0[setup->softpipe->layer_slot];
      layer = MIN2(layer, setup->max_layer);
   }
   setup->quad[0].input.layer = layer;

   if (setup->softpipe->viewport_index_slot > 0) {
      unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
      viewport_index = sp_clamp_viewport_idx(*udata);
   }
   setup->quad[0].input.viewport_index = viewport_index;

   /* For points, all interpolants are constant-valued.
    * However, for point sprites, we'll need to setup texcoords appropriately.
    * XXX: which coefficients are the texcoords???
    * We may do point sprites as textured quads...
    *
    * KW: We don't know which coefficients are texcoords - ultimately
    * the choice of what interpolation mode to use for each attribute
    * should be determined by the fragment program, using
    * per-attribute declaration statements that include interpolation
    * mode as a parameter.  So either the fragment program will have
    * to be adjusted for pointsprite vs normal point behaviour, or
    * otherwise a special interpolation mode will have to be defined
    * which matches the required behaviour for point sprites.  But -
    * the latter is not a feature of normal hardware, and as such
    * probably should be ruled out on that basis.
    */
   setup->vprovoke = v0;

   /* setup Z, W */
   const_coeff(setup, &setup->posCoef, 0, 2);
   const_coeff(setup, &setup->posCoef, 0, 3);

   for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
      const uint vertSlot = sinfo->attrib[fragSlot].src_index;
      uint j;

      switch (sinfo->attrib[fragSlot].interp) {
      case SP_INTERP_CONSTANT:
         /* fall-through */
      case SP_INTERP_LINEAR:
         for (j = 0; j < TGSI_NUM_CHANNELS; j++)
            const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
         break;
      case SP_INTERP_PERSPECTIVE:
         for (j = 0; j < TGSI_NUM_CHANNELS; j++)
            point_persp_coeff(setup, setup->vprovoke,
                              &setup->coef[fragSlot], vertSlot, j);
         break;
      case SP_INTERP_POS:
         setup_fragcoord_coeff(setup, fragSlot);
         break;
      default:
         assert(0);
      }

      if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
         /* convert 0 to 1.0 and 1 to -1.0 */
         setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
         setup->coef[fragSlot].dadx[0] = 0.0;
         setup->coef[fragSlot].dady[0] = 0.0;
      }
   }


   if (halfSize <= 0.5 && !round) {
      /* special case for 1-pixel points */
      const int ix = ((int) x) & 1;
      const int iy = ((int) y) & 1;
      setup->quad[0].input.x0 = (int) x - ix;
      setup->quad[0].input.y0 = (int) y - iy;
      setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
      clip_emit_quad(setup, &setup->quad[0]);
   }
   else {
      if (round) {
         /* rounded points */
         const int ixmin = block((int) (x - halfSize));
         const int ixmax = block((int) (x + halfSize));
         const int iymin = block((int) (y - halfSize));
         const int iymax = block((int) (y + halfSize));
         const float rmin = halfSize - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
         const float rmax = halfSize + 0.7071F;
         const float rmin2 = MAX2(0.0F, rmin * rmin);
         const float rmax2 = rmax * rmax;
         const float cscale = 1.0F / (rmax2 - rmin2);
         int ix, iy;

         for (iy = iymin; iy <= iymax; iy += 2) {
            for (ix = ixmin; ix <= ixmax; ix += 2) {
               float dx, dy, dist2, cover;

               setup->quad[0].inout.mask = 0x0;

               dx = (ix + 0.5f) - x;
               dy = (iy + 0.5f) - y;
               dist2 = dx * dx + dy * dy;
               if (dist2 <= rmax2) {
                  cover = 1.0F - (dist2 - rmin2) * cscale;
                  setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
                  setup->quad[0].inout.mask |= MASK_TOP_LEFT;
               }

               dx = (ix + 1.5f) - x;
               dy = (iy + 0.5f) - y;
               dist2 = dx * dx + dy * dy;
               if (dist2 <= rmax2) {
                  cover = 1.0F - (dist2 - rmin2) * cscale;
                  setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
                  setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
               }

               dx = (ix + 0.5f) - x;
               dy = (iy + 1.5f) - y;
               dist2 = dx * dx + dy * dy;
               if (dist2 <= rmax2) {
                  cover = 1.0F - (dist2 - rmin2) * cscale;
                  setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
                  setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
               }

               dx = (ix + 1.5f) - x;
               dy = (iy + 1.5f) - y;
               dist2 = dx * dx + dy * dy;
               if (dist2 <= rmax2) {
                  cover = 1.0F - (dist2 - rmin2) * cscale;
                  setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
                  setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
               }

               if (setup->quad[0].inout.mask) {
                  setup->quad[0].input.x0 = ix;
                  setup->quad[0].input.y0 = iy;
                  clip_emit_quad(setup, &setup->quad[0]);
               }
            }
         }
      }
      else {
         /* square points */
         const int xmin = (int) (x + 0.75 - halfSize);
         const int ymin = (int) (y + 0.25 - halfSize);
         const int xmax = xmin + (int) size;
         const int ymax = ymin + (int) size;
         /* XXX could apply scissor to xmin,ymin,xmax,ymax now */
         const int ixmin = block(xmin);
         const int ixmax = block(xmax - 1);
         const int iymin = block(ymin);
         const int iymax = block(ymax - 1);
         int ix, iy;

         /*
         debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
         */
         for (iy = iymin; iy <= iymax; iy += 2) {
            uint rowMask = 0xf;
            if (iy < ymin) {
               /* above the top edge */
               rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
            }
            if (iy + 1 >= ymax) {
               /* below the bottom edge */
               rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
            }

            for (ix = ixmin; ix <= ixmax; ix += 2) {
               uint mask = rowMask;

               if (ix < xmin) {
                  /* fragment is past left edge of point, turn off left bits */
                  mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
               }
               if (ix + 1 >= xmax) {
                  /* past the right edge */
                  mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
               }

               setup->quad[0].inout.mask = mask;
               setup->quad[0].input.x0 = ix;
               setup->quad[0].input.y0 = iy;
               clip_emit_quad(setup, &setup->quad[0]);
            }
         }
      }
   }
}
Ejemplo n.º 4
0
/**
 * Do setup for line rasterization, then render the line.
 * Single-pixel width, no stipple, etc.  We rely on the 'draw' module
 * to handle stippling and wide lines.
 */
void
sp_setup_line(struct setup_context *setup,
              const float (*v0)[4],
              const float (*v1)[4])
{
   int x0 = (int) v0[0][0];
   int x1 = (int) v1[0][0];
   int y0 = (int) v0[0][1];
   int y1 = (int) v1[0][1];
   int dx = x1 - x0;
   int dy = y1 - y0;
   int xstep, ystep;
   uint layer = 0;
   unsigned viewport_index = 0;

#if DEBUG_VERTS
   debug_printf("Setup line:\n");
   print_vertex(setup, v0);
   print_vertex(setup, v1);
#endif

   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
      return;

   if (dx == 0 && dy == 0)
      return;

   if (!setup_line_coefficients(setup, v0, v1))
      return;

   assert(v0[0][0] < 1.0e9);
   assert(v0[0][1] < 1.0e9);
   assert(v1[0][0] < 1.0e9);
   assert(v1[0][1] < 1.0e9);

   if (dx < 0) {
      dx = -dx;   /* make positive */
      xstep = -1;
   }
   else {
      xstep = 1;
   }

   if (dy < 0) {
      dy = -dy;   /* make positive */
      ystep = -1;
   }
   else {
      ystep = 1;
   }

   assert(dx >= 0);
   assert(dy >= 0);
   assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);

   setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
   setup->quad[0].inout.mask = 0x0;
   if (setup->softpipe->layer_slot > 0) {
      layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot];
      layer = MIN2(layer, setup->max_layer);
   }
   setup->quad[0].input.layer = layer;

   if (setup->softpipe->viewport_index_slot > 0) {
      unsigned *udata = (unsigned*)setup->vprovoke[setup->softpipe->viewport_index_slot];
      viewport_index = sp_clamp_viewport_idx(*udata);
   }
   setup->quad[0].input.viewport_index = viewport_index;

   /* XXX temporary: set coverage to 1.0 so the line appears
    * if AA mode happens to be enabled.
    */
   setup->quad[0].input.coverage[0] =
   setup->quad[0].input.coverage[1] =
   setup->quad[0].input.coverage[2] =
   setup->quad[0].input.coverage[3] = 1.0;

   if (dx > dy) {
      /*** X-major line ***/
      int i;
      const int errorInc = dy + dy;
      int error = errorInc - dx;
      const int errorDec = error - dx;

      for (i = 0; i < dx; i++) {
         plot(setup, x0, y0);

         x0 += xstep;
         if (error < 0) {
            error += errorInc;
         }
         else {
            error += errorDec;
            y0 += ystep;
         }
      }
   }
   else {
      /*** Y-major line ***/
      int i;
      const int errorInc = dx + dx;
      int error = errorInc - dy;
      const int errorDec = error - dy;

      for (i = 0; i < dy; i++) {
         plot(setup, x0, y0);

         y0 += ystep;
         if (error < 0) {
            error += errorInc;
         }
         else {
            error += errorDec;
            x0 += xstep;
         }
      }
   }

   /* draw final quad */
   if (setup->quad[0].inout.mask) {
      clip_emit_quad(setup, &setup->quad[0]);
   }
}
Ejemplo n.º 5
0
/**
 * Do setup for triangle rasterization, then render the triangle.
 */
void sp_setup_tri( struct setup_context *setup,
                const float (*v0)[4],
                const float (*v1)[4],
                const float (*v2)[4] )
{
   float det;

#if DEBUG_VERTS
   debug_printf("Setup triangle:\n");
   print_vertex(setup, v0);
   print_vertex(setup, v1);
   print_vertex(setup, v2);
#endif

   if (setup->softpipe->no_rast)
      return;
   
   det = calc_det(v0, v1, v2);
   /*
   debug_printf("%s\n", __FUNCTION__ );
   */

#if DEBUG_FRAGS
   setup->numFragsEmitted = 0;
   setup->numFragsWritten = 0;
#endif

   if (cull_tri( setup, det ))
      return;

   if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
      return;
   setup_tri_coefficients( setup );
   setup_tri_edges( setup );

   assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);

   setup->span.y = 0;
   setup->span.right[0] = 0;
   setup->span.right[1] = 0;
   /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */

   /*   init_constant_attribs( setup ); */

   if (setup->oneoverarea < 0.0) {
      /* emaj on left:
       */
      subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
      subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
   }
   else {
      /* emaj on right:
       */
      subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
      subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
   }

   flush_spans( setup );

#if DEBUG_FRAGS
   printf("Tri: %u frags emitted, %u written\n",
          setup->numFragsEmitted,
          setup->numFragsWritten);
#endif
}
Ejemplo n.º 6
0
/**
 * Sort vertices from top to bottom.
 * Compute area and determine front vs. back facing.
 * Do coarse clip test against tile bounds
 * \return  FALSE if tri is totally outside tile, TRUE otherwise
 */
static boolean
setup_sort_vertices(const qword vs)
{
   float area, sign;

#if DEBUG_VERTS
   if (spu.init.id==0) {
      fprintf(stderr, "SPU %u: Triangle:\n", spu.init.id);
      print_vertex(v0);
      print_vertex(v1);
      print_vertex(v2);
   }
#endif

   {
      /* Load the float values for various processing... */
      const qword f0 = (qword)(((const struct vertex_header*)si_to_ptr(vs))->data[0]);
      const qword f1 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 4)))->data[0]);
      const qword f2 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 8)))->data[0]);

      /* Check if triangle is completely outside the tile bounds
       * Find the min and max x and y positions of the three poits */
      const qword minf = min3fq(f0, f1, f2);
      const qword maxf = max3fq(f0, f1, f2);

      /* Compare min and max against cliprect vals */
      const qword maxsmins = si_shufb(maxf, minf, SHUFB4(A,B,a,b));
      const qword outside = si_fcgt(maxsmins, si_csflt(setup.cliprect, 0));

      /* Use a little magic to work out of the tri is visible or not */
      if(si_to_uint(si_xori(si_gb(outside), 0xc))) return FALSE;

      /* determine bottom to top order of vertices */
      /* A table of shuffle patterns for putting vertex_header pointers into
         correct order.  Quite magical. */
      const qword sort_order_patterns[] = {
         SHUFB4(A,B,C,C),
         SHUFB4(C,A,B,C),
         SHUFB4(A,C,B,C),
         SHUFB4(B,C,A,C),
         SHUFB4(B,A,C,C),
         SHUFB4(C,B,A,C) };

      /* Collate y values into two vectors for comparison.
         Using only one shuffle constant! ;) */
      const qword y_02_ = si_shufb(f0, f2, SHUFB4(0,B,b,C));
      const qword y_10_ = si_shufb(f1, f0, SHUFB4(0,B,b,C));
      const qword y_012 = si_shufb(y_02_, f1, SHUFB4(0,B,b,C));
      const qword y_120 = si_shufb(y_10_, f2, SHUFB4(0,B,b,C));

      /* Perform comparison: {y0,y1,y2} > {y1,y2,y0} */
      const qword compare = si_fcgt(y_012, y_120);
      /* Compress the result of the comparison into 4 bits */
      const qword gather = si_gb(compare);
      /* Subtract one to attain the index into the LUT.  Magical. */
      const unsigned int index = si_to_uint(gather) - 1;

      /* Load the appropriate pattern and construct the desired vector. */
      setup.vertex_headers = si_shufb(vs, vs, sort_order_patterns[index]);

      /* Using the result of the comparison, set sign.
         Very magical. */
      sign = ((si_to_uint(si_cntb(gather)) == 2) ? 1.0f : -1.0f);
   }

   setup.ebot.ds = spu_sub(setup.vmid->data[0], setup.vmin->data[0]);
   setup.emaj.ds = spu_sub(setup.vmax->data[0], setup.vmin->data[0]);
   setup.etop.ds = spu_sub(setup.vmax->data[0], setup.vmid->data[0]);

   /*
    * Compute triangle's area.  Use 1/area to compute partial
    * derivatives of attributes later.
    */
   area = setup.emaj.dx * setup.ebot.dy - setup.ebot.dx * setup.emaj.dy;

   setup.oneOverArea = 1.0f / area;

   /* The product of area * sign indicates front/back orientation (0/1).
    * Just in case someone gets the bright idea of switching the front
    * and back constants without noticing that we're assuming their
    * values in this operation, also assert that the values are
    * what we think they are.
    */
   ASSERT(CELL_FACING_FRONT == 0);
   ASSERT(CELL_FACING_BACK == 1);
   setup.facing = (area * sign > 0.0f)
      ^ (spu.rasterizer.front_winding == PIPE_WINDING_CW);

   return TRUE;
}
Ejemplo n.º 7
0
/**
 * Do setup for line rasterization, then render the line.
 * Single-pixel width, no stipple, etc.  We rely on the 'draw' module
 * to handle stippling and wide lines.
 */
void
setup_line(struct setup_context *setup,
           const float (*v0)[4],
           const float (*v1)[4])
{
   int x0 = (int) v0[0][0];
   int x1 = (int) v1[0][0];
   int y0 = (int) v0[0][1];
   int y1 = (int) v1[0][1];
   int dx = x1 - x0;
   int dy = y1 - y0;
   int xstep, ystep;

#if DEBUG_VERTS
   debug_printf("Setup line:\n");
   print_vertex(setup, v0);
   print_vertex(setup, v1);
#endif

   if (setup->softpipe->no_rast)
      return;

   if (dx == 0 && dy == 0)
      return;

   if (!setup_line_coefficients(setup, v0, v1))
      return;

   assert(v0[0][0] < 1.0e9);
   assert(v0[0][1] < 1.0e9);
   assert(v1[0][0] < 1.0e9);
   assert(v1[0][1] < 1.0e9);

   if (dx < 0) {
      dx = -dx;   /* make positive */
      xstep = -1;
   }
   else {
      xstep = 1;
   }

   if (dy < 0) {
      dy = -dy;   /* make positive */
      ystep = -1;
   }
   else {
      ystep = 1;
   }

   assert(dx >= 0);
   assert(dy >= 0);

   setup->quad.input.x0 = setup->quad.input.y0 = -1;
   setup->quad.inout.mask = 0x0;
   setup->quad.input.prim = QUAD_PRIM_LINE;
   /* XXX temporary: set coverage to 1.0 so the line appears
    * if AA mode happens to be enabled.
    */
   setup->quad.input.coverage[0] =
   setup->quad.input.coverage[1] =
   setup->quad.input.coverage[2] =
   setup->quad.input.coverage[3] = 1.0;

   if (dx > dy) {
      /*** X-major line ***/
      int i;
      const int errorInc = dy + dy;
      int error = errorInc - dx;
      const int errorDec = error - dx;

      for (i = 0; i < dx; i++) {
         plot(setup, x0, y0);

         x0 += xstep;
         if (error < 0) {
            error += errorInc;
         }
         else {
            error += errorDec;
            y0 += ystep;
         }
      }
   }
   else {
      /*** Y-major line ***/
      int i;
      const int errorInc = dx + dx;
      int error = errorInc - dy;
      const int errorDec = error - dy;

      for (i = 0; i < dy; i++) {
         plot(setup, x0, y0);

         y0 += ystep;
         if (error < 0) {
            error += errorInc;
         }
         else {
            error += errorDec;
            x0 += xstep;
         }
      }
   }

   /* draw final quad */
   if (setup->quad.inout.mask) {
      CLIP_EMIT_QUAD(setup);
   }

   WAIT_FOR_COMPLETION(setup);
}
Ejemplo n.º 8
0
/*
 *                                M A I N ( )
 */
int
main (int argc, char **argv)
{
    char		*label[2];	/* Labels of edge endpoints */
    int			ch;		/* Command-line character */
    int			i;
    int			numeric = 0;	/* Use vertex indices (vs. labels)? */
    long		index[2];	/* Indices of edge endpoints */
    double		weight;		/* Edge weight */
    bu_rb_tree		*dictionary;	/* Dictionary of vertices */
    struct bridge	*bp;		/* The current bridge */
    struct vertex	*up;		/* An uncivilized neighbor of vup */
    struct vertex	*vcp;		/* The civilized vertex of bp */
    struct vertex	*vup;		/* The uncivilized vertex of bp */
    struct vertex	*vertex[2];	/* The current edge */
    struct neighbor	*neighbor[2];	/* Their neighbors */
    struct neighbor	*np;		/* A neighbor of vup */
    int			(*po[2])();	/* Priority queue order functions */

    while ((ch = bu_getopt(argc, argv, OPT_STRING)) != EOF)
	switch (ch)
	{
	    case 'n':
		numeric = 1;
		break;
	    case '?':
	    default:
		print_usage();
		bu_exit (ch != '?', NULL);
		return(0);
	}

    /*
     *	Initialize the dictionary
     */
    dictionary = bu_rb_create1("Dictionary of vertices",
			       numeric ? compare_vertex_indices
			       : compare_vertex_labels);
    bu_rb_uniq_on1(dictionary);

    /*
     *	Read in the graph
     */
    while (get_edge(stdin, index, label, &weight, numeric))
    {
	for (i = 0; i < 2; ++i)		/* For each end of the edge... */
	{
	    vertex[i] = lookup_vertex(dictionary, index[i], label[i]);
	    neighbor[i] = mk_neighbor(VERTEX_NULL, weight);
	    BU_LIST_INSERT(&(vertex[i] -> v_neighbors), &(neighbor[i] -> l));
	}
	neighbor[0] -> n_vertex = vertex[1];
	neighbor[1] -> n_vertex = vertex[0];
    }

    /*
     *	Initialize the priority queue
     */
    po[PRIOQ_INDEX] = compare_bridge_indices;
    po[PRIOQ_WEIGHT] = compare_bridge_weights;
    prioq = bu_rb_create("Priority queue of bridges", 2, po);
    bu_rb_walk1(dictionary, add_to_prioq, INORDER);

    if (debug)
    {
	print_prioq();
	bu_rb_walk1(dictionary, print_vertex, INORDER);
    }

    /*
     *	Grow a minimum spanning tree, using Prim's algorithm...
     *
     *	While there exists a min-weight bridge (to a vertex v) in the queue
     *	    Dequeue the bridge
     *	    If the weight is finite
     *	        Output the bridge
     *	    Mark v as civilized
     *	    For every uncivilized neighbor u of v
     *	        if uv is cheaper than u's current bridge
     *		    dequeue u's current bridge
     *		    enqueue bridge(uv)
     */
    weight = 0.0;
    while ((bp = extract_min()) != BRIDGE_NULL)
    {
	if (debug)
	{
	    bu_log("extracted min-weight bridge <x%x>, leaving...\n", bp);
	    print_prioq();
	}

	BU_CKMAG(bp, BRIDGE_MAGIC, "bridge");
	vcp = bp -> b_vert_civ;
	vup = bp -> b_vert_unciv;
	BU_CKMAG(vup, VERTEX_MAGIC, "vertex");

	if (is_finite_bridge(bp))
	{
	    BU_CKMAG(vcp, VERTEX_MAGIC, "vertex");
	    if (numeric)
		(void) printf("%ld %ld %g\n",
			      vcp -> v_index, vup -> v_index, bp -> b_weight);
	    else
		(void) printf("%s %s %g\n",
			      vcp -> v_label, vup -> v_label, bp -> b_weight);
	    weight += bp -> b_weight;
	}
	free_bridge(bp);
	vup -> v_civilized = 1;

	if (debug)
	{
	    bu_log("Looking for uncivilized neighbors of...\n");
	    print_vertex((void *) vup, 0);
	}
	while (BU_LIST_WHILE(np, neighbor, &(vup -> v_neighbors)))
	{
	    BU_CKMAG(np, NEIGHBOR_MAGIC, "neighbor");
	    up = np -> n_vertex;
	    BU_CKMAG(up, VERTEX_MAGIC, "vertex");

	    if (up -> v_civilized == 0)
	    {
		BU_CKMAG(up -> v_bridge, BRIDGE_MAGIC, "bridge");
		if (compare_weights(np -> n_weight,
				    up -> v_bridge -> b_weight) < 0)
		{
		    del_from_prioq(up);
		    if (debug)
		    {
			bu_log("After the deletion of bridge <x%x>...\n",
			       up -> v_bridge);
			print_prioq();
		    }
		    up -> v_bridge -> b_vert_civ = vup;
		    up -> v_bridge -> b_weight = np -> n_weight;
		    add_to_prioq((void *) up, 0);
		    if (debug)
		    {
			bu_log("Reduced bridge <x%x> weight to %g\n",
			       up -> v_bridge,
			       up -> v_bridge -> b_weight);
			print_prioq();
		    }
		}
		else if (debug)
		    bu_log("bridge <x%x>'s weight of %g stands up\n",
			   up -> v_bridge, up -> v_bridge -> b_weight);
	    }
	    else if (debug)
		bu_log("Skipping civilized neighbor <x%x>\n", up);
	    BU_LIST_DEQUEUE(&(np -> l));
	}
    }

    bu_log("MST weight: %g\n", weight);
    return 0;
}