Esempio n. 1
0
//Calibrates the sensor
void calibrate(unsigned int *sensors, unsigned int *minv, unsigned int *maxv) {
	//say something to the user
	clear();
	lcd_goto_xy(0, 0);
	print(" Fluffy");
	lcd_goto_xy(0, 1);
	print("A=Go!");
	
	//wait on the calibration button
	wait_for_button_press(BUTTON_A);
	
	//wait for the user to move his hand
	delay_ms(500);

	//activate the motors
	set_motors(40, -40);
	
	//take 165 readings from the sensors...why not?
	int i;
	for (i = 0; i < 165; i++) {
		read_line_sensors(sensors, IR_EMITTERS_ON);
		update_bounds(sensors, minv, maxv);
		delay_ms(10);
	}

	//and turn the motors off, we're done
	set_motors(0, 0);
	
	delay_ms(750);
}
Esempio n. 2
0
void WT_Drawable::update_bounds(const WT_Logical_Point* pts, int count, WT_File * file)
{
    for (int i=0; i<count; i++)
    {
        update_bounds(pts[i], file);
    }
}
Esempio n. 3
0
static void force_update(void) {
    status_update();

    time_t now = time(NULL);
    update_time(localtime(&now));

    update_bounds();
}
Esempio n. 4
0
WT_Logical_Box WT_Drawable::bounds (WT_File * file)
{
    if (m_bounds_set == WD_False)
    {
        m_bounds.m_min = WT_Logical_Point(0x7FFFFFFF,0x7FFFFFFF);
        m_bounds.m_max = WT_Logical_Point(0x80000000,0x80000000);
        update_bounds(file);
        m_bounds_set = WD_True;
    }
    return m_bounds;
}
Esempio n. 5
0
void Mesh::transform_vertices(const Matrix &transform, const Matrix &normal_transform)
{
	for(size_t i = 0; i < m_vertices.size(); ++i) {
		Matrix::transform(m_original_vertices[i], transform, m_vertices[i]);
	}

	for(size_t i = 0; i < m_normals.size(); ++i) {
		Matrix::transform(m_original_normals[i], normal_transform, m_normals[i]);
		m_normals[i].normalize();
	}

	update_bounds();
}
Esempio n. 6
0
// ----------------------------------------------------------------------------
// -- Function    : private add(val)
// --
// -- Takes       : val = the value to add to the array
// --
// -- Purpose     : Adds a value to the array, making sure the array never
//                  becomes larger than m_maxValueCount
void ValueHistoryTable::add(double val)
{
    // Make sure the array size is 1 less than the max count
    if (int(m_values->size()) >= m_maxValuesCount)
    {
        // We need to prune the array by removing the oldest value
        remove_oldest();
    }

    // Add the value to the end of the array
    m_values->push_back(val);

    // Update the bounds
    update_bounds(val);
}
Esempio n. 7
0
bool
MapCanvas::visible(const Canvas &canvas,
                   const RasterPoint *screen, unsigned num)
{
  PixelRect bounds;
  bounds.left = 0x7fff;
  bounds.top = 0x7fff;
  bounds.right = -1;
  bounds.bottom = -1;

  for (unsigned i = 0; i < num; ++i)
    update_bounds(bounds, screen[i]);

  return bounds.left < (int)canvas.get_width() && bounds.right >= 0 &&
    bounds.top < (int)canvas.get_height() && bounds.bottom >= 0;
}
Esempio n. 8
0
//-------------------------------------------------------------------------
void Prg_ASCEND::update_fbd()
{
  int i, idx, row_idx;
  int m, me;
  int32 calc_ok;
  double residual, mult;

  // write current optimization variables to ASCEND
  for (i = 0; i < _nvars; i++) {
    idx = _var_asc2hqp[i];
    if (idx >= 0)
      var_set_value(_vars[i], _x[idx]);
  }

  // update variable bounds
  update_bounds();

  // update objective
  _f = relman_eval(_obj, &calc_ok, _safe_calc);
  _slv_status.calc_ok &= calc_ok;

  // update general constraints
  me = _me_bounds;
  m = _m_bounds;
  for (i = 0; i < _nrels; i++) {
    residual = relman_eval(_rels[i], &calc_ok, _safe_calc);
    _slv_status.calc_ok &= calc_ok;
    if (rel_equal(_rels[i])) {
      row_idx = me++;
      _qp->b[row_idx] = residual;
    }
    else {
      row_idx = m++;
      mult = rel_less(_rels[i])? -1.0: 1.0;
      _qp->d[row_idx] = mult * residual;
    }
  }
}
Esempio n. 9
0
Mesh::Mesh(	const std::string &name, 
			const std::vector<Vector3f> &vertices, 
			const std::vector<uint16_t> &indices,
			const std::vector<Vector3f> &normals, 
			const std::vector<Vector3f> &tangents,
			const std::vector<Vector3f> &bitangents, 
			const std::vector<Vector2f> &texture_coords,
			const std::shared_ptr<Material> &material)
	: 		m_name(name), 
			m_original_vertices(vertices),
			m_vertices(vertices),
			m_indices(indices),
			m_original_normals(normals),
			m_normals(normals),
			m_tangents(tangents),
			m_bitangents(bitangents),
			m_texture_coords(texture_coords),
			m_material(material),
			m_bounds(AABB(Vector3f(FLT_MAX), Vector3f(-FLT_MAX)))

{
	update_bounds();
}
Esempio n. 10
0
int constraint_init(hsignature_t *sig)
{
    /* Make a copy of the signature. */
    hsignature_copy(&local_sig, sig);

    /* Initialize layer variables. */
    if (strategy_cfg(sig) != 0)
        return -1;

    if (build_vars_text(sig) != 0)
        return -1;

    if (build_bounds_text(sig) != 0)
        return -1;

    if (build_user_text() != 0)
        return -1;

    /* Calculate the range for each tuning variable, given the constraints. */
    if (update_bounds(sig) != 0)
        return -1;

    return 0;
}
Esempio n. 11
0
/*!
 * \brief Contructor for ShapeInfo from file
 * 
 * Load the full shape info from file potentially reusing the preloaded
 * ShapeInfo loaded by shape_typeinfo_load()
 *
 * \extends _ShapeInfo
 */
static ShapeInfo *
load_shape_info(const gchar *filename, ShapeInfo *preload)
{
  xmlErrorPtr error_xml = NULL;
  xmlDocPtr doc = xmlDoParseFile(filename, &error_xml);
  xmlNsPtr shape_ns, svg_ns;
  xmlNodePtr node, root, ext_node = NULL;
  ShapeInfo *info;
  gchar *tmp;
  int i;
  
  if (!doc) {
    g_warning("Custom shape parser error for %s\n%s", filename,
	      error_xml ? error_xml->message : "");
    return NULL;
  }
  /* skip (emacs) comments */
  root = doc->xmlRootNode;
  while (root && (root->type != XML_ELEMENT_NODE)) root = root->next;
  if (!root) return NULL;
  if (xmlIsBlankNode(root)) return NULL;

  if (!(shape_ns = xmlSearchNsByHref(doc, root,
		(const xmlChar *)"http://www.daa.com.au/~james/dia-shape-ns"))) {
    xmlFreeDoc(doc);
    g_warning("could not find shape namespace");
    return NULL;
  }
  if (!(svg_ns = xmlSearchNsByHref(doc, root, (const xmlChar *)"http://www.w3.org/2000/svg"))) {
    xmlFreeDoc(doc);
    g_warning("could not find svg namespace");
    return NULL;
  }
  if (root->ns != shape_ns || xmlStrcmp(root->name, (const xmlChar *)"shape")) {
    g_warning("root element was %s -- expecting shape", root->name);
    xmlFreeDoc(doc);
    return NULL;
  }

  if (preload)
    info = preload;
  else 
    info = g_new0(ShapeInfo, 1);
  info->loaded = TRUE;
  info->shape_bounds.top = DBL_MAX;
  info->shape_bounds.left = DBL_MAX;
  info->shape_bounds.bottom = -DBL_MAX;
  info->shape_bounds.right = -DBL_MAX;
  info->aspect_type = SHAPE_ASPECT_FREE; 
  info->default_width = 0.0;
  info->default_height = 0.0;
  info->main_cp = -1;
  info->object_flags = 0;

  i = 0;
  for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
    if (xmlIsBlankNode(node)) continue;
    if (node->type != XML_ELEMENT_NODE) continue;
    if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"name")) {
      tmp = (gchar *) xmlNodeGetContent(node);
      if (preload) { 
        if (strcmp (tmp, info->name) != 0)
          g_warning ("Shape(preload) '%s' can't change name '%s'", info->name, tmp);
        /* the key name is already used as key in name_to_info */
      } else {
        g_free(info->name);
        info->name = g_strdup(tmp);
      }
      xmlFree(tmp);
    } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"icon")) {
      tmp = (gchar *) xmlNodeGetContent(node);
      if (preload) { 
        if (strstr (info->icon, tmp) == NULL) /* the left including the absolute path */
          g_warning ("Shape(preload) '%s' can't change icon '%s'", info->icon, tmp);
        /* the key name is already used as key in name_to_info */
      } else {
        g_free(info->icon);
        info->icon = custom_get_relative_filename(filename, tmp);
      }
      xmlFree(tmp);
    } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"connections")) {
      GArray *arr = g_array_new(FALSE, FALSE, sizeof(Point));
      xmlNodePtr pt_node;

      for (pt_node = node->xmlChildrenNode; 
           pt_node != NULL; 
           pt_node = pt_node->next) {
        if (xmlIsBlankNode(pt_node)) continue;

	if (pt_node->ns == shape_ns && !xmlStrcmp(pt_node->name, (const xmlChar *)"point")) {
	  Point pt = { 0.0, 0.0 };
	  xmlChar *str;

	  str = xmlGetProp(pt_node, (const xmlChar *)"x");
	  if (str) {
	    pt.x = g_ascii_strtod((gchar *) str, NULL);
	    xmlFree(str);
	  }
	  str = xmlGetProp(pt_node, (const xmlChar *)"y");
	  if (str) {
	    pt.y = g_ascii_strtod((gchar *) str, NULL);
	    xmlFree(str);
	  }
	  g_array_append_val(arr, pt);
	  str = xmlGetProp(pt_node, (const xmlChar *)"main");
	  if (str && str[0] != '\0') {
	    if (info->main_cp != -1) {
	      message_warning("More than one main connection point in %s.  Only the first one will be used.\n",
			      info->name);
	    } else {
	      info->main_cp = i;
	    }
	    xmlFree(str);
	  }
	}
	i++;
      }
      info->nconnections = arr->len;
      info->connections = (Point *)arr->data;
      g_array_free(arr, FALSE);
    } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"can-parent")) {
      info->object_flags |= DIA_OBJECT_CAN_PARENT;
    } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"textbox")) {
      xmlChar *str;
      
      str = xmlGetProp(node, (const xmlChar *)"x1");
      if (str) {
	info->text_bounds.left = g_ascii_strtod((gchar *) str, NULL);
	xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"y1");
      if (str) {
	info->text_bounds.top = g_ascii_strtod((gchar *) str, NULL);
	xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"x2");
      if (str) {
	info->text_bounds.right = g_ascii_strtod((gchar *) str, NULL);
	xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"y2");
      if (str) {
	info->text_bounds.bottom = g_ascii_strtod((gchar *) str, NULL);
	xmlFree(str);
      }
      info->resize_with_text = TRUE;
      str = xmlGetProp(node, (const xmlChar *)"resize");
      if (str) {
        info->resize_with_text = TRUE;
        if (!xmlStrcmp(str,(const xmlChar *)"no"))
          info->resize_with_text = FALSE;
	xmlFree(str);
      }
      info->text_align = ALIGN_CENTER;
      str = xmlGetProp(node, (const xmlChar *)"align");
      if (str) {
	if (!xmlStrcmp(str, (const xmlChar *)"left")) 
	  info->text_align = ALIGN_LEFT;
	else if (!xmlStrcmp(str, (const xmlChar *)"right"))
	  info->text_align = ALIGN_RIGHT;
	xmlFree(str);
      }
      info->has_text = TRUE;
    } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"aspectratio")) {
      tmp = (gchar *) xmlGetProp(node, (const xmlChar *)"type");
      if (tmp) {
	if (!strcmp(tmp, "free"))
	  info->aspect_type = SHAPE_ASPECT_FREE;
	else if (!strcmp(tmp, "fixed"))
	  info->aspect_type = SHAPE_ASPECT_FIXED;
	else if (!strcmp(tmp, "range")) {
	  xmlChar *str;

	  info->aspect_type = SHAPE_ASPECT_RANGE;
	  info->aspect_min = 0.0;
	  info->aspect_max = G_MAXFLOAT;
	  str = xmlGetProp(node, (const xmlChar *)"min");
	  if (str) {
	    info->aspect_min = g_ascii_strtod((gchar *) str, NULL);
	    xmlFree(str);
	  }
	  str = xmlGetProp(node, (const xmlChar *)"max");
	  if (str) {
	    info->aspect_max = g_ascii_strtod((gchar *) str, NULL);
	    xmlFree(str);
	  }
	  if (info->aspect_max < info->aspect_min) {
	    real asp = info->aspect_max;
	    info->aspect_max = info->aspect_min;
	    info->aspect_min = asp;
	  }
	}
	xmlFree(tmp);
      }
    } else if (node->ns == shape_ns && (!xmlStrcmp(node->name, (const xmlChar *)"default-width") || !xmlStrcmp(node->name, (const xmlChar *)"default-height"))) {
      
      int j = 0;
      DiaUnitDef ud;
      
      gdouble val = 0.0;
      
      int unit_ssize = 0;
      int ssize = 0;
      tmp = (gchar *) xmlNodeGetContent(node);
      ssize = strlen(tmp);

      val = g_ascii_strtod(tmp, NULL);

      for (ud = units[j]; ud.name; ud = units[++j]) {
        unit_ssize = strlen(ud.unit);
        if (ssize > unit_ssize && !strcmp(tmp+(ssize-unit_ssize), ud.unit)) {
          val *= (ud.factor / 28.346457);
          break;
        }
      }

      if (!xmlStrcmp(node->name, (const xmlChar *)"default-width")) {
        info->default_width = val;
      } else {
        info->default_height = val;
      }
      
      xmlFree(tmp);
    } else if (node->ns == svg_ns && !xmlStrcmp(node->name, (const xmlChar *)"svg")) {
      DiaSvgStyle s = {
	1.0, DIA_SVG_COLOUR_FOREGROUND, 1.0, DIA_SVG_COLOUR_NONE, 1.0,
	DIA_SVG_LINECAPS_DEFAULT, DIA_SVG_LINEJOIN_DEFAULT, DIA_SVG_LINESTYLE_DEFAULT, 1.0
      };

      dia_svg_parse_style(node, &s, -1);
      parse_svg_node(info, node, svg_ns, &s, filename);
      update_bounds(info);
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"ext_attributes")) {
      ext_node = node;
    }
  }
  /*MC 11/03 parse ext attributes if any & prepare prop tables */
  custom_setup_properties (info, ext_node);
  xmlFreeDoc(doc);
  return info;
}
Esempio n. 12
0
/*!
 * \brief Parse the SVG node from a shape file
 * 
 * Fill the ShapeInfo display list with GraphicElement each got from
 * a single node within the shape's SVG part.
 *
 * \extends _ShapeInfo
 */
static void
parse_svg_node(ShapeInfo *info, xmlNodePtr node, xmlNsPtr svg_ns,
               DiaSvgStyle *style, const gchar *filename)
{
  xmlChar *str;

      /* walk SVG node ... */
  for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
    GraphicElement *el = NULL;
    DiaSvgStyle s;

    if (xmlIsBlankNode(node)) continue;
    if (node->type != XML_ELEMENT_NODE || node->ns != svg_ns)
      continue;
    dia_svg_style_init (&s, style);
    dia_svg_parse_style(node, &s, -1);
    if (!xmlStrcmp(node->name, (const xmlChar *)"line")) {
      GraphicElementLine *line = g_new0(GraphicElementLine, 1);

      el = (GraphicElement *)line;
      line->type = GE_LINE;
      str = xmlGetProp(node, (const xmlChar *)"x1");
      if (str) {
        line->p1.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"y1");
      if (str) {
        line->p1.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"x2");
      if (str) {
        line->p2.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"y2");
      if (str) {
        line->p2.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"polyline")) {
      GraphicElementPoly *poly;
      GArray *arr = g_array_new(FALSE, FALSE, sizeof(real));
      real val, *rarr;
      gchar *tmp;
      int i;

      str = xmlGetProp(node, (const xmlChar *)"points");
      tmp = (gchar *) str;
      while (tmp[0] != '\0') {
            /* skip junk */
        while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-')
          tmp++;
        if (tmp[0] == '\0') break;
        val = g_ascii_strtod(tmp, &tmp);
        g_array_append_val(arr, val);
      }
      xmlFree(str);
      val = 0;
      if (arr->len % 2 == 1) 
        g_array_append_val(arr, val);
      poly = g_malloc0(sizeof(GraphicElementPoly) + arr->len/2*sizeof(Point));
      el = (GraphicElement *)poly;
      poly->type = GE_POLYLINE;
      poly->npoints = arr->len / 2;
      rarr = (real *)arr->data;
      for (i = 0; i < poly->npoints; i++) {
        poly->points[i].x = rarr[2*i];
        poly->points[i].y = rarr[2*i+1];
      }
      g_array_free(arr, TRUE);
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"polygon")) {
      GraphicElementPoly *poly;
      GArray *arr = g_array_new(FALSE, FALSE, sizeof(real));
      real val, *rarr;
      char *tmp;
      int i;

      str = xmlGetProp(node, (const xmlChar *)"points");
      tmp = (char *) str;
      while (tmp[0] != '\0') {
            /* skip junk */
        while (tmp[0] != '\0' && !g_ascii_isdigit(tmp[0]) && tmp[0]!='.'&&tmp[0]!='-')
          tmp++;
        if (tmp[0] == '\0') break;
        val = g_ascii_strtod(tmp, &tmp);
        g_array_append_val(arr, val);
      }
      xmlFree(str);
      val = 0;
      if (arr->len % 2 == 1) 
        g_array_append_val(arr, val);
      poly = g_malloc0(sizeof(GraphicElementPoly) + arr->len/2*sizeof(Point));
      el = (GraphicElement *)poly;
      poly->type = GE_POLYGON;
      poly->npoints = arr->len / 2;
      rarr = (real *)arr->data;
      for (i = 0; i < poly->npoints; i++) {
        poly->points[i].x = rarr[2*i];
        poly->points[i].y = rarr[2*i+1];
      }
      g_array_free(arr, TRUE);
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"rect")) {
      GraphicElementRect *rect = g_new0(GraphicElementRect, 1);
      real corner_radius = 0.0;

      el = (GraphicElement *)rect;
      rect->type = GE_RECT;
      str = xmlGetProp(node, (const xmlChar *)"x");
      if (str) {
        rect->corner1.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      } else rect->corner1.x = 0;
      str = xmlGetProp(node, (const xmlChar *)"y");
      if (str) {
        rect->corner1.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      } else rect->corner1.y = 0;
      str = xmlGetProp(node, (const xmlChar *)"width");
      if (str) {
        rect->corner2.x = rect->corner1.x + g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"height");
      if (str) {
        rect->corner2.y = rect->corner1.y + g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"rx");
      if (str) {
        corner_radius = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"ry");
      if (str) {
        if(corner_radius != 0.0) {
          /* calculate the mean value of rx and ry */
          corner_radius = (corner_radius+g_ascii_strtod((gchar *) str, NULL))/2;
        } else {
          corner_radius = g_ascii_strtod((gchar *) str, NULL);
        }
        xmlFree(str);
      }
      rect->corner_radius = corner_radius;
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"text")) {

      GraphicElementText *text = g_new(GraphicElementText, 1);
      el = (GraphicElement *)text;
      text->type = GE_TEXT;
      text->object = NULL;
      str = xmlGetProp(node, (const xmlChar *)"x");
      if (str) {
        text->anchor.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      } else text->anchor.x = 0;
      str = xmlGetProp(node, (const xmlChar *)"y");
      if (str) {
        text->anchor.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      } else text->anchor.y = 0;

      str = xmlGetProp(node, (const xmlChar *)"font-size");
      if (str) {
        text->s.font_height = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      } else text->s.font_height = 0.8;

      str = xmlNodeGetContent(node);
      if (str) {
        text->string = g_strdup((gchar *) str);
        xmlFree(str);
      } else text->string = g_strdup("");
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"circle")) {
      GraphicElementEllipse *ellipse = g_new0(GraphicElementEllipse, 1);

      el = (GraphicElement *)ellipse;
      ellipse->type = GE_ELLIPSE;
      str = xmlGetProp(node, (const xmlChar *)"cx");
      if (str) {
        ellipse->center.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"cy");
      if (str) {
        ellipse->center.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"r");
      if (str) {
        ellipse->width = ellipse->height = 2 * g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"ellipse")) {
      GraphicElementEllipse *ellipse = g_new0(GraphicElementEllipse, 1);

      el = (GraphicElement *)ellipse;
      ellipse->type = GE_ELLIPSE;
      str = xmlGetProp(node, (const xmlChar *)"cx");
      if (str) {
        ellipse->center.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"cy");
      if (str) {
        ellipse->center.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"rx");
      if (str) {
        ellipse->width = 2 * g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"ry");
      if (str) {
        ellipse->height = 2 * g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"path")) {
      str = xmlGetProp(node, (const xmlChar *)"d");
      if (str) {
        parse_path(info, (char *) str, &s, filename);
        xmlFree(str);
      }
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"image")) {
      GraphicElementImage *image = g_new0(GraphicElementImage, 1);

      el = (GraphicElement *)image;
      image->type = GE_IMAGE;
      str = xmlGetProp(node, (const xmlChar *)"x");
      if (str) {
        image->topleft.x = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"y");
      if (str) {
        image->topleft.y = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"width");
      if (str) {
        image->width = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"height");
      if (str) {
        image->height = g_ascii_strtod((gchar *) str, NULL);
        xmlFree(str);
      }
      str = xmlGetProp(node, (const xmlChar *)"xlink:href");
      if (!str) /* this doesn't look right but it appears to work w/o namespace --hb */
        str = xmlGetProp(node, (const xmlChar *)"href");
      if (str) {
        gchar *imgfn = NULL;
        const char* data = strchr((char *)str, ',');

	/* first check for inlined data */
	if (data) {
	  GdkPixbuf *pixbuf = pixbuf_decode_base64 (data+1);

	  if (pixbuf) {
	    image->image = dia_image_new_from_pixbuf (pixbuf);
	    g_object_unref (pixbuf);
	  }
	} else {
	  imgfn = g_filename_from_uri((gchar *) str, NULL, NULL);
          if (!imgfn)
	    /* despite it's name it ensures an absolute filename */
            imgfn = custom_get_relative_filename(filename, (gchar *) str);

          image->image = dia_image_load(imgfn);
	}
        if (!image->image)
          g_debug("failed to load image file %s", imgfn ? imgfn : "(data:)");
        g_free(imgfn);
        xmlFree(str);
      }
      /* w/o the image we would crash later */
      if (!image->image)
        image->image = dia_image_get_broken();
    } else if (!xmlStrcmp(node->name, (const xmlChar *)"g")) {
      if (!is_subshape(node)) {
          /* add elements from the group element */
        parse_svg_node(info, node, svg_ns, &s, filename);
      } else {
          /* add elements from the group element, but make it a subshape */
        GraphicElementSubShape *subshape = g_new0(GraphicElementSubShape, 1);
        ShapeInfo* tmpinfo = g_new0(ShapeInfo, 1);
        xmlChar *v_anchor_attr = xmlGetProp(node, (const xmlChar*)"v_anchor");
        xmlChar *h_anchor_attr = xmlGetProp(node, (const xmlChar*)"h_anchor");
      
        parse_svg_node(tmpinfo, node, svg_ns, &s, filename);
        
        tmpinfo->shape_bounds.top = DBL_MAX;
        tmpinfo->shape_bounds.left = DBL_MAX;
        tmpinfo->shape_bounds.bottom = -DBL_MAX;
        tmpinfo->shape_bounds.right = -DBL_MAX;

        update_bounds( tmpinfo );
        update_bounds( info );
        
        subshape->half_width = (tmpinfo->shape_bounds.right-tmpinfo->shape_bounds.left) / 2.0;
        subshape->half_height = (tmpinfo->shape_bounds.bottom-tmpinfo->shape_bounds.top) / 2.0;
        subshape->center.x = tmpinfo->shape_bounds.left + subshape->half_width;
        subshape->center.y = tmpinfo->shape_bounds.top + subshape->half_height;
            
        subshape->type = GE_SUBSHAPE;
        subshape->display_list = tmpinfo->display_list;
        subshape->v_anchor_method = OFFSET_METHOD_FIXED;
        subshape->h_anchor_method = OFFSET_METHOD_FIXED;
        subshape->default_scale = 0.0;
                
        if (!v_anchor_attr || !strcmp((const char*)v_anchor_attr,"fixed.top"))
          subshape->v_anchor_method = OFFSET_METHOD_FIXED;
        else if (v_anchor_attr && !strcmp((const char*)v_anchor_attr,"fixed.bottom"))
          subshape->v_anchor_method = -OFFSET_METHOD_FIXED;
        else if (v_anchor_attr && !strcmp((const char*)v_anchor_attr,"proportional"))
          subshape->v_anchor_method = OFFSET_METHOD_PROPORTIONAL;
        else
          fprintf( stderr, "illegal v_anchor `%s', defaulting to fixed.top\n",
                   v_anchor_attr );
          
        if (!h_anchor_attr || !strcmp((const char*)h_anchor_attr,"fixed.left"))
          subshape->h_anchor_method = OFFSET_METHOD_FIXED;
        else if (h_anchor_attr && !strcmp((const char*)h_anchor_attr,"fixed.right"))
          subshape->h_anchor_method = -OFFSET_METHOD_FIXED;
        else if (h_anchor_attr && !strcmp((const char*)h_anchor_attr,"proportional"))
          subshape->h_anchor_method = OFFSET_METHOD_PROPORTIONAL;
        else
          fprintf( stderr, "illegal h_anchor `%s', defaulting to fixed.left\n",
                   h_anchor_attr );
        
        info->subshapes = g_list_append(info->subshapes, subshape);
        
        /* gfree( tmpinfo );*/
        xmlFree(v_anchor_attr);
        xmlFree(h_anchor_attr);
        
        el = (GraphicElement *)subshape;
      }    
    }
    if (el) {
      el->any.s = s;
      if (el->any.s.font)
        el->any.s.font = g_object_ref(s.font);
      info->display_list = g_list_append(info->display_list, el);
    }
    if (s.font)
      dia_font_unref (s.font);
  }
}
Esempio n. 13
0
void
bezier_do_action(VALUE points, texture_info * tex, VALUE hash_arg, texplay_sync sync_mode,
                 bool primary, action_struct * payload)
{
    float u = 0.0;
    action_struct cur;
    float x1, y1, x2, y2;
    int first_x, first_y;
    int format;
    int num_point_pairs;
    bool closed = false;
    VALUE offset_val;
    int draw_offset_x, draw_offset_y;

    /* defaults to 200 (1 / 0.005) samples per curve */
    float step_size = 0.005;
    
    draw_prologue(&cur, tex, XMAX_OOB, YMAX_OOB, XMIN_OOB, YMIN_OOB, &hash_arg, sync_mode, primary, &payload);

    /* calculate offset */
    offset_val = get_image_local(tex->image, DRAW_OFFSET);

    draw_offset_x = NUM2INT(get_from_array(offset_val, 0));
    draw_offset_y = NUM2INT(get_from_array(offset_val, 1));

    if(is_a_hash(hash_arg)) {

        /* if the polyline is 'closed' make the last point the first */
        if(RTEST(get_from_hash(hash_arg, "closed")) || RTEST(get_from_hash(hash_arg, "close"))) {

            /* so that our additional point is not persistent */
            points = rb_obj_dup(points);
            closed = true;
        }
        
        /* number of points to sample */
        if(RTEST(get_from_hash(hash_arg, "sample_size"))) {
            VALUE c = get_from_hash(hash_arg, "sample_size");
            Check_Type(c, T_FIXNUM);
            step_size = 1.0 / (float)FIX2INT(c);
        }
    }

    if(is_a_point(get_from_array(points, 0))) {
        format = POINT_FORMAT;

        if(closed)
            rb_ary_push(points, get_from_array(points, 0));
        
        num_point_pairs = RARRAY_LEN(points);
    }
    else {
        format = SIMPLE_FORMAT;

        /* ensure points are given in pairs */
        if(RARRAY_LEN(points) % 2)
            rb_raise(rb_eArgError, "bezier needs an even number of points. got %d\n", (int)RARRAY_LEN(points));

        if(closed) {
            rb_ary_push(points, get_from_array(points, 0));
            rb_ary_push(points, get_from_array(points, 1));
        }
        
        num_point_pairs = RARRAY_LEN(points) / 2;
    }

    if(num_point_pairs > 17)
        rb_raise(rb_eArgError, "too many points for bezier curve. 17 points is current maximum. got %d\n",
                 num_point_pairs);

    /* get the first point */
    bezier_point(points, 0, &x1, &y1, num_point_pairs, format, draw_offset_x, draw_offset_y);

    /* save it so we can link up with last point properly if the curve is 'closed' */
    first_x = x1;
    first_y = y1;

    while(u <= 1) {
        bezier_point(points, u, &x2, &y2, num_point_pairs, format, draw_offset_x, draw_offset_y);
 
        line_do_action(x1, y1, x2, y2, tex, hash_arg, no_sync, false, payload);

        /* update drawing rectangle */
        update_bounds(payload, x1, y1, x2, y2);

        x1 = x2;
        y1 = y2;

        u += step_size;
    }

    /* sometimes beziers dont close properly, so we'll ensure it's closed */
    if(closed)
        line_do_action(x2, y2, first_x, first_y, tex, hash_arg, no_sync, false, payload);

    draw_epilogue(&cur, tex, primary);
}
Esempio n. 14
0
int AnnulusKmeans::runThread(int threadId, int maxIterations) {
    int iterations = 0;

    int startNdx = start(threadId);
    int endNdx = end(threadId);

    while ((iterations < maxIterations) && ! converged) {
        ++iterations;

        update_s(threadId);
        synchronizeAllThreads();

        if (threadId == 0) {
            // compute the inter-center distances, keeping only the closest distances
            sort_means_by_norm();
        }
        synchronizeAllThreads();

        // loop over all records
        for (int i = startNdx; i < endNdx; ++i) {
            unsigned short closest = assignment[i];

            // if upper[i] is less than the greater of these two, then we can
            // ignore record i
            double upper_comparison_bound = std::max(s[closest], lower[i]);

            // first check: if u(x) <= s(c(x)) or u(x) <= lower(x), then ignore
            // x, because its closest center must still be closest
            if (upper[i] <= upper_comparison_bound) {
                continue;
            }

            // otherwise, compute the real distance between this record and its
            // closest center, and update upper
            double u2 = pointCenterDist2(i, closest);
            upper[i] = sqrt(u2);

            // if (u(x) <= s(c(x))) or (u(x) <= lower(x)), then ignore x
            if (upper[i] <= upper_comparison_bound) {
                continue;
            }

            double l2 = pointCenterDist2(i, guard[i]);
            lower[i] = sqrt(l2);

            double beta = std::max(lower[i], upper[i]);

            std::pair<double, int>* begin = std::lower_bound(cOrder, cOrder + k, std::make_pair(xNorm[i] - beta, k));
            std::pair<double, int>* end = std::lower_bound(begin, cOrder + k, std::make_pair(xNorm[i] + beta, k));

            for (std::pair<double, int>* jp = begin; jp != end; ++jp) {
                if (jp->second == closest) continue;

                double dist2 = pointCenterDist2(i, jp->second);
                if (dist2 <= u2) {
                    if (dist2 == u2) {
                        if (jp->second < closest) closest = jp->second;
                    } else {
                        l2 = u2;
                        u2 = dist2;
                        guard[i] = closest;
                        closest = jp->second;
                    }
                } else if (dist2 < l2) {
                    // we must reduce the lower bound on the distance to the
                    // *second* closest center to x[i]
                    l2 = dist2;
                    guard[i] = jp->second;
                }
            }

            // we have been dealing in squared distances; need to convert
            lower[i] = sqrt(l2);

            // if the assignment for i has changed, then adjust the counts and
            // locations of each center's accumulated mass
            if (assignment[i] != closest) {
                upper[i] = sqrt(u2);
                changeAssignment(i, closest, threadId);
            }
        }

        verifyAssignment(iterations, startNdx, endNdx);

        // ELKAN 4, 5, AND 6
        // calculate the new center locations
        synchronizeAllThreads();
        if (threadId == 0) {
            int furthestMovingCenter = move_centers();
            converged = (0.0 == centerMovement[furthestMovingCenter]);
        }

        synchronizeAllThreads();

        if (! converged) {
            update_bounds(startNdx, endNdx);
        }

        synchronizeAllThreads();
    }

    return iterations;
}
Esempio n. 15
0
//-------------------------------------------------------------------------
void Prg_ASCEND::update(const VECP y, const VECP z)
{
  var_filter_t vfilter;
  int i, j, row_idx, idx;
  int m, me;
  int32 count;
  int status, newel;
  real64 residual;
  double mult;
  SPMAT *J;

  // write current optimization variables to ASCEND
  for (j = 0; j < _nvars; j++) {
    idx = _var_asc2hqp[j];
    if (idx >= 0)
      var_set_value(_vars[j], _x[idx]);
  }

  // update variable bounds
  update_bounds();

  // initialize vfilter so that all optimization variables are considered
  vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED);
  vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR);

  // update objective and derivatives
  status = relman_diff_grad(_obj, &vfilter, _derivatives->ve,
			    _var_master_idxs->ive, _var_solver_idxs->ive,
			    &count, &residual, _safe_calc);
  if (status == 0) // todo: this contradicts docu in solver/relman.h!?
    _slv_status.calc_ok &= FALSE;
  _f = residual;
  for (j = 0; j < count; j++) {
    idx = _var_asc2hqp[_var_solver_idxs[j]];
    if (idx >= 0)
      _qp->c[idx] = _derivatives[j];
  }

  // update general constraints
  me = _me_bounds;
  m = _m_bounds;
  newel = 0;
  for (i = 0; i < _nrels; i++) {
    status = relman_diff_grad(_rels[i], &vfilter, _derivatives->ve,
			      _var_master_idxs->ive, _var_solver_idxs->ive,
			      &count, &residual, _safe_calc);
    if (status == 0) // todo: this contradicts docu in solver/relman.h!?
      _slv_status.calc_ok &= FALSE;
    if (rel_equal(_rels[i])) {
      row_idx = me++;
      mult = 1.0;
      _qp->b[row_idx] = residual;
      J = _qp->A;
    }
    else {
      row_idx = m++;
      mult = rel_less(_rels[i])? -1.0: 1.0;
      _qp->d[row_idx] = mult * residual;
      J = _qp->C;
    }
    sprow_zero(J->row + row_idx);
    for (j = 0; j < count; j++) {
      idx = _var_asc2hqp[_var_solver_idxs[j]];
      if (idx >= 0)
	newel |= sp_update_val(J, row_idx, idx, mult * _derivatives[j]);
    }      
  }
  if (newel) {
    // the sparsity structure has changed
    _slv_status.ok = FALSE;
    _slv_status.inconsistent = TRUE;
    _slv_status.ready_to_solve = FALSE;
  }
}
Esempio n. 16
0
static void handle_unobstructed_change(AnimationProgress progress, void *context) {
    update_bounds();
}
Esempio n. 17
0
// this version only updates center locations when necessary
int HamerlyKmeans::runThread(int threadId, int maxIterations) {
    int iterations = 0;

    int startNdx = start(threadId);
    int endNdx = end(threadId);

    while ((iterations < maxIterations) && ! converged) {
        ++iterations;

        // compute the inter-center distances, keeping only the closest distances
        update_s(threadId);
        synchronizeAllThreads();

        // loop over all records
        for (int i = startNdx; i < endNdx; ++i) {
            unsigned short closest = assignment[i];

            // if upper[i] is less than the greater of these two, then we can
            // ignore record i
            double upper_comparison_bound = std::max(s[closest], lower[i]);

            // first check: if u(x) <= s(c(x)) or u(x) <= lower(x), then ignore
            // x, because its closest center must still be closest
            if (upper[i] <= upper_comparison_bound) {
                continue;
            }

            // otherwise, compute the real distance between this record and its
            // closest center, and update upper
            double u2 = pointCenterDist2(i, closest);
            upper[i] = sqrt(u2);

            // if (u(x) <= s(c(x))) or (u(x) <= lower(x)), then ignore x
            if (upper[i] <= upper_comparison_bound) {
                continue;
            }

            // now update the lower bound by looking at all other centers
            double l2 = std::numeric_limits<double>::max(); // the squared lower bound
            for (int j = 0; j < k; ++j) {
                if (j == closest) { continue; }

                double dist2 = pointCenterDist2(i, j);

                if (dist2 < u2) {
                    // another center is closer than the current assignment

                    // change the lower bound to be the current upper bound
                    // (since the current upper bound is the distance to the
                    // now-second-closest known center)
                    l2 = u2;

                    // adjust the upper bound and the current assignment
                    u2 = dist2;
                    closest = j;
                } else if (dist2 < l2) {
                    // we must reduce the lower bound on the distance to the
                    // *second* closest center to x[i]
                    l2 = dist2;
                }
            }

            // we have been dealing in squared distances; need to convert
            lower[i] = sqrt(l2);

            // if the assignment for i has changed, then adjust the counts and
            // locations of each center's accumulated mass
            if (assignment[i] != closest) {
                upper[i] = sqrt(u2);
                changeAssignment(i, closest, threadId);
            }
        }

        verifyAssignment(iterations, startNdx, endNdx);

        // ELKAN 4, 5, AND 6
        // calculate the new center locations
        synchronizeAllThreads();
        if (threadId == 0) {
            int furthestMovingCenter = move_centers();
            converged = (0.0 == centerMovement[furthestMovingCenter]);
        }

        synchronizeAllThreads();

        if (! converged) {
            update_bounds(startNdx, endNdx);
        }

        synchronizeAllThreads();
    }

    return iterations;
}
Esempio n. 18
0
void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)
{
    // reset bounds
    _reset_bounds_flag = true;

    if (_useShaders)
    {
        // Update shader uniforms
        // This slightly reduces the consumption of traversing the particle vector, because we
        // don't compute tile and angle attributes that are useleff for shaders.
        // At present, our lcoal shader implementation will ignore these particle props:
        //     _cur_tile, _s_coord, _t_coord, _prev_pos, _prev_angle and _angle
        osg::StateSet* stateset = getOrCreateStateSet();

        if (_dirty_uniforms)
        {
            osg::Uniform* u_vd = stateset->getUniform("visibilityDistance");
            if (u_vd) u_vd->set((float)_visibilityDistance);
            _dirty_uniforms = false;
        }
    }

    for(unsigned int i=0; i<_particles.size(); ++i)
    {
        Particle& particle = _particles[i];
        if (particle.isAlive())
        {
            if (particle.update(dt, _useShaders))
            {
                update_bounds(particle.getPosition(), particle.getCurrentSize());
            }
            else
            {
                reuseParticle(i);
            }
        }
    }

    if (_sortMode != NO_SORT)
    {
        // sort particles
        osgUtil::CullVisitor* cv = nv.asCullVisitor();
        if (cv)
        {
            osg::Matrixd modelview = *(cv->getModelViewMatrix());
            double scale = (_sortMode==SORT_FRONT_TO_BACK ? -1.0 : 1.0);
            double deadDistance = DBL_MAX;
            for (unsigned int i=0; i<_particles.size(); ++i)
            {
                Particle& particle = _particles[i];
                if (particle.isAlive())
                    particle.setDepth(distance(particle.getPosition(), modelview) * scale);
                else
                    particle.setDepth(deadDistance);
            }
            std::sort<Particle_vector::iterator>(_particles.begin(), _particles.end());

            // Repopulate the death stack as it will have been invalidated by the sort.
            unsigned int numDead = _deadparts.size();
            if (numDead>0)
            {
                 // clear the death stack
                _deadparts = Death_stack();

                // copy the tail of the _particles vector as this will contain all the dead Particle thanks to the depth sort against DBL_MAX
                Particle* first_dead_ptr  = &_particles[_particles.size()-numDead];
                Particle* last_dead_ptr  = &_particles[_particles.size()-1];
                for(Particle* dead_ptr  = first_dead_ptr; dead_ptr<=last_dead_ptr; ++dead_ptr)
                {
                    _deadparts.push(dead_ptr);
                }
            }
        }
    }

    // force recomputing of bounding box on next frame
    dirtyBound();
}
Esempio n. 19
0
void WT_Drawable::update_bounds(const WT_Point_Set& set, WT_File * file)
{
    update_bounds(set.points(), set.count(), file);
}
Esempio n. 20
0
void
scan_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg,
                    texplay_sync sync_mode, bool primary, action_struct * payload)
{
    action_struct cur;
    rgba old_color;
    int y1;
    bool spanLeft, spanRight;

    if(!bound_by_rect(x, y, 0, 0, tex->width - 1, tex->height - 1)) return;

    /* NB: using XMAX_OOB etc since we dont know the drawing area yet; drawing area will be set by
       update_bounds() function in main loop */
    draw_prologue(&cur, tex, XMAX_OOB, YMAX_OOB, XMIN_OOB, YMIN_OOB, &hash_arg, sync_mode, primary, &payload);

    /* fill hates alpha_blend so let's turn it off */
    payload->pen.alpha_blend = false;
    
    old_color = get_pixel_color(tex, x, y);

    if(cmp_color(old_color, cur.color)) return;
    
    emptyStack();
    
    if(!push(x, y, tex->width - 1)) return;
    
    while(pop(&x, &y, tex->width - 1))
        {    
            y1 = y;
            while(y1 >= 0 && cmp_color(old_color, get_pixel_color(tex, x, y1))) y1--;
            y1++;
            spanLeft = spanRight = false;
            while(y1 < tex->height && cmp_color(old_color, get_pixel_color(tex, x, y1)) )
                {
                    set_pixel_color_with_style(payload, tex, x, y1);

                    /* update the drawing rectangle */
                    update_bounds(payload, x, y1, x, y1);

                    if(!spanLeft && x > 0 && cmp_color(old_color, get_pixel_color(tex, x - 1, y1))) 
                        {
                            if(!push(x - 1, y1, tex->width - 1)) return;
                            spanLeft = true;
                        }

                    else if(spanLeft && !cmp_color(old_color, get_pixel_color(tex, x - 1, y1)))
                        {
                            spanLeft = false;
                        }

                    if(!spanRight && x < tex->width - 1 && cmp_color(old_color,
                                                                     get_pixel_color(tex, x + 1, y1))) 
                        {
                            if(!push(x + 1, y1, tex->width - 1)) return;
                            spanRight = true;
                        }

                    else if(spanRight && x < tex->width - 1 && !cmp_color(old_color,get_pixel_color(tex, x + 1, y1)))
                        {
                            spanRight = false;
                        } 
                    y1++;
                }
        }
    draw_epilogue(&cur, tex, primary);
}
Esempio n. 21
0
int ElkanKmeans::runThread(int threadId, int maxIterations) {
    int iterations = 0;

    int startNdx = start(threadId);
    int endNdx = end(threadId);

    while ((iterations < maxIterations) && ! converged) {
        ++iterations;

        update_center_dists(threadId);
        synchronizeAllThreads();

        for (int i = startNdx; i < endNdx; ++i) {
            unsigned short closest = assignment[i];
            bool r = true;

            if (upper[i] <= s[closest]) {
                continue;
            }

            for (int j = 0; j < k; ++j) {
                if (j == closest) { continue; }
                if (upper[i] <= lower[i * k + j]) { continue; }
                if (upper[i] <= centerCenterDistDiv2[closest * k + j]) { continue; }

                // ELKAN 3(a)
                if (r) {
                    upper[i] = sqrt(pointCenterDist2(i, closest));
                    lower[i * k + closest] = upper[i];
                    r = false;
                    if ((upper[i] <= lower[i * k + j]) || (upper[i] <= centerCenterDistDiv2[closest * k + j])) {
                        continue;
                    }
                }

                // ELKAN 3(b)
                lower[i * k + j] = sqrt(pointCenterDist2(i, j));
                if (lower[i * k + j] < upper[i]) {
                    closest = j;
                    upper[i] = lower[i * k + j];
                }
            }
            if (assignment[i] != closest) {
                changeAssignment(i, closest, threadId);
            }
        }

        verifyAssignment(iterations, startNdx, endNdx);

        // ELKAN 4, 5, AND 6
        synchronizeAllThreads();
        if (threadId == 0) {
            int furthestMovingCenter = move_centers();
            converged = (0.0 == centerMovement[furthestMovingCenter]);
        }

        synchronizeAllThreads();
        if (! converged) {
            update_bounds(startNdx, endNdx);
        }
        synchronizeAllThreads();
    }

    return iterations;
}
Esempio n. 22
0
void
polyline_do_action(VALUE points, texture_info * tex, VALUE hash_arg,
                   texplay_sync sync_mode, bool primary, action_struct * payload)
{

    int x1, y1, x2, y2;
    int format;
    int num_point_pairs;
    int k;
    int draw_offset_y, draw_offset_x;
    action_struct cur;
    VALUE offset_val;
    bool closed = false;
    
    draw_prologue(&cur, tex, XMAX_OOB, YMAX_OOB, XMIN_OOB, YMIN_OOB, &hash_arg, sync_mode, primary, &payload);

    /* calculate offset */
    offset_val = get_image_local(tex->image, DRAW_OFFSET);

    draw_offset_x = NUM2INT(get_from_array(offset_val, 0));
    draw_offset_y = NUM2INT(get_from_array(offset_val, 1));

    /* if the polyline is 'closed' make the last point the first */
    if(is_a_hash(hash_arg))
        if(RTEST(get_from_hash(hash_arg, "closed")) || RTEST(get_from_hash(hash_arg, "close"))) {
            
            /* so that our additional point is not persistent */
            points = rb_obj_dup(points);
            closed = true;
        }
    /* determine format of points */
    if(is_a_point(get_from_array(points, 0))) {
        format = POINT_FORMAT;

        /* if the polyline is closed to form a polygon then make the last point and first point identical */
        if(closed)
            rb_ary_push(points, get_from_array(points, 0));

        num_point_pairs = RARRAY_LEN(points);
    }
    else {
        format = SIMPLE_FORMAT;

        /* ensure there is an 'x' for every 'y'  */
        if(RARRAY_LEN(points) % 2)
            rb_raise(rb_eArgError, "polyline needs an even number of points. got %d\n",
                     (int)RARRAY_LEN(points));

        if(closed) {
            rb_ary_push(points, get_from_array(points, 0));
            rb_ary_push(points, get_from_array(points, 1));
        }

        num_point_pairs = RARRAY_LEN(points) / 2;
    }

    /* calculate first point */
    polyline_point(points, 0, &x1, &y1, format, draw_offset_x, draw_offset_y);
    
    /* calc the points and draw the polyline */
    for(k = 1; k < num_point_pairs; k++) {

        polyline_point(points, k, &x2, &y2, format, draw_offset_x, draw_offset_y);
    
        line_do_action(x1, y1, x2, y2, tex, hash_arg, no_sync, false, payload);

        /* update drawing rectangle */
        update_bounds(payload, x1, y1, x2, y2);
        
        x1 = x2; y1 = y2;
    }
    
    draw_epilogue(&cur, tex, primary);
}