Пример #1
0
void Vectorizer::load_data(const char* filename)
{
  FILE* f = fopen(filename, "rb");
  if (f == NULL) error("Could not open %s for reading.", filename);
  lock_data();

  struct { char magic[4]; int ver; } hdr;
  if (fread(&hdr, sizeof(hdr), 1, f) != 1)
    error("Error reading %s", filename);

  if (hdr.magic[0] != 'H' || hdr.magic[1] != '2' || hdr.magic[2] != 'D' || hdr.magic[3] != 'V')
    error("File %s is not a Hermes2D Vectorizer file.", filename);
  if (hdr.ver > 1)
    error("File %s -- unsupported file version.", filename);

  #define read_array(array, type, n, c, what) \
    if (fread(&n, sizeof(int), 1, f) != 1) \
      error("Error reading the number of " what " from %s", filename); \
    lin_init_array(array, type, c, n); \
    if (fread(array, sizeof(type), n, f) != n) \
      error("Error reading " what " from %s", filename);

  read_array(verts, double4, nv, cv, "vertices");
  read_array(tris,  int3,    nt, ct, "triangles");
  read_array(edges, int3,    ne, ce, "edges");
  read_array(dashes, int2,   nd, cd, "dashes");

  find_min_max();
  unlock_data();
  fclose(f);
}
Пример #2
0
void
shell_unzoom(int x, int y)
{
    Evas_Coord              ex, ey, ew, eh;

    if (!drawing)
        return;
    evas_output_viewport_get(shell->evas, &ex, &ey, &ew, &eh);

    lock_data();
    y = eh + ey - y;

    drawing->old.x = drawing->x;
    drawing->old.y = drawing->y;
    drawing->old.scale = drawing->scale;

    drawing->x -= x / drawing->scale;
    drawing->y -= y / drawing->scale;
    drawing->scale /= 1.25;
    drawing->x += x / drawing->scale;
    drawing->y += y / drawing->scale;

    append_undo_double((void *)(&(drawing->x)), drawing->old.x,
                       drawing->x, 1, OBJ_DRAWING, NULL);
    append_undo_double((void *)(&(drawing->y)), drawing->old.y,
                       drawing->y, 0, 0, NULL);
    append_undo_double((void *)(&(drawing->scale)), drawing->old.scale,
                       drawing->scale, 0, 0, NULL);

    unlock_data();
    drawing_sync();
}
Пример #3
0
void
line_create(void)
{
    char               *s;
    float               x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    int                 res;

    serv_set_hint(DUP(_("enter first point: ")));

    serv_set_state(ST_LINE1);

    do
      {
          s = serv_get_string();
          res = get_values(s, shell->context.fx, shell->context.fy, &x1, &y1);
          if (res == 1)
              serv_set_hint(DUP(_("error, please reenter: ")));
      }
    while (res == 1);

    serv_set_state(ST_LINE2);

    if (res == 0)
      {
          serv_set_state(ST_NORMAL);
          return;
      }

    do
      {
          pre_line_x1y1(x1, y1);
          shell->context.fx = x1;
          shell->context.fy = y1;

          serv_set_hint(DUP(_("enter next point: ")));
          do
            {
                s = serv_get_string();
                res = get_values(s, x1, y1, &x2, &y2);
                if (res == 1)
                    serv_set_hint(DUP(_("error, please reenter: ")));
            }
          while (res == 1);
          if (res == 0)
            {
                serv_set_state(ST_NORMAL);
                return;
            }

          lock_data();
          _line_create(x1, y1, x2, y2);
          shell->context.fx = x2;
          shell->context.fy = y2;
          unlock_data();
          x1 = x2;
          y1 = y2;
      }
    while (1);
}
Пример #4
0
bool FmMsg::retrieve(FmMsgEntry * dst) {
	if (!lock_data() || _buf.empty()) {
		return false;
	} else {
		dst = &_buf.front();
		unlock_data();
		return true;
	}
}
Пример #5
0
bool Thread_Pool::add_work (std::unique_ptr<Pool_Work> work)
{
    if (pool.size() == 0)
        return false;

    std::unique_lock<std::mutex> lock_data (data_mtx);

    queue.push_back (std::move(work));
	cond.notify_one();

    return true;
}
Пример #6
0
FmMsgEntry FmMsg::retrieve() {
	if (!lock_data() || _buf.empty()) {
		FmMsgEntry ret(0, RAW);
		return ret;
	} else {
		FmMsgEntry ret(_buf.front(), OWNERSHIP); 
		_buf.pop();
		unlock_data();
		--_cnt;
		return ret;
	}
}
Пример #7
0
bool FmMsg::insert(FmMsgEntry * src) {
	if (_cnt == _max) {
		_handle(src);
		return false;
	}

	while(!lock_data());
	_buf.push(*src);
	unlock_data();

	++_cnt;

	return true;
}
Пример #8
0
      void Orderizer::save_data_vtk(const char* file_name)
      {
        FILE* f = fopen(file_name, "wb");
        if (f == NULL) error("Could not open %s for writing.", file_name);
        lock_data();

        // Output header for vertices.
        fprintf(f, "# vtk DataFile Version 2.0\n");
        fprintf(f, "\n");
        fprintf(f, "ASCII\n\n");
        fprintf(f, "DATASET UNSTRUCTURED_GRID\n");

        // Output vertices.
        fprintf(f, "POINTS %d %s\n", this->nv, "float");
        for (int i=0; i < this->nv; i++) 
        {
          fprintf(f, "%g %g %g\n", this->verts[i][0], this->verts[i][1], 0.0);
        }

        // Output elements.
        fprintf(f, "\n");
        fprintf(f, "CELLS %d %d\n", this->nt, 4 * this->nt);
        for (int i=0; i < this->nt; i++) 
        {
          fprintf(f, "3 %d %d %d\n", this->tris[i][0], this->tris[i][1], this->tris[i][2]);
        }

        // Output cell types.
        fprintf(f, "\n");
        fprintf(f, "CELL_TYPES %d\n", this->nt);
        for (int i=0; i < this->nt; i++) 
        {
          fprintf(f, "5\n");    // The "5" means triangle in VTK.
        }

        // This outputs double solution values. Look into Hermes2D/src/output/vtk.cpp 
        // for how it is done for vectors.
        fprintf(f, "\n");
        fprintf(f, "POINT_DATA %d\n", this->nv);
        fprintf(f, "SCALARS %s %s %d\n", "Mesh", "float", 1);
        fprintf(f, "LOOKUP_TABLE %s\n", "default");
        for (int i=0; i < this->nv; i++) 
        {
          fprintf(f, "%g\n", this->verts[i][2]);
        }

        unlock_data();
        fclose(f);
      }
Пример #9
0
void
shell_drag_start(int x, int y)
{

    if (!drawing)
        return;
    pointer_push_and_set(0x1500 + POINTER_HAND);
    drag = 1;
    drag_x = x;
    drag_y = y;
    lock_data();
    drawing->old.x = drawing->x;
    drawing->old.y = drawing->y;
    unlock_data();
}
Пример #10
0
bool FmMsg::insert(int size, void * content, FmMsgEntry_type type) {
	FmMsgEntry dst(size, type);
	dst.populate(content, size, type);

	if (_cnt == _max) {
		_handle(&dst);
		return false;
	}

	while (!lock_data()); // wait for the lock.
	_buf.push(dst);
	unlock_data();

	++_cnt;

	return true;
}
Пример #11
0
void Thread_Pool::working_thread (Thread_Pool *obj,
									std::shared_ptr<Work_State_Overlay> state)
{
	while (Work_State_Overlay::KEEP_WORKING == *state) {
		std::unique_lock<std::mutex> lock_data (obj->data_mtx);
		if (Work_State_Overlay::KEEP_WORKING != *state)
			break;
		if (obj->queue.size() == 0) {
			*state = Work_State_Overlay::WAITING;
			obj->cond.wait (lock_data);
			if (Work_State_Overlay::WAITING != *state)	// => abort
				break;
			if (obj->queue.size() == 0)	{ // unlock intended for other threads?
				*state = Work_State_Overlay::KEEP_WORKING;
				lock_data.unlock();
				continue;
			}
			*state = Work_State_Overlay::KEEP_WORKING;
		}

		std::unique_ptr<Pool_Work> my_work = std::move(obj->queue.front());
		obj->queue.pop_front();
		lock_data.unlock();

		auto exit_stat = my_work->do_work (
					reinterpret_cast<RaptorQ__v1::Work_State *> (state.get()));

		switch (exit_stat) {
		case Work_Exit_Status::DONE:
			break;
		case Work_Exit_Status::STOPPED:
			lock_data.lock();
			obj->queue.push_front (std::move(my_work));
			obj->cond.notify_one();
			lock_data.unlock();
			break;
		case Work_Exit_Status::REQUEUE:
			lock_data.lock();
			obj->queue.push_back (std::move(my_work));
			obj->cond.notify_one();
			lock_data.unlock();
			break;
		}
	}
}
Пример #12
0
void
shell_drag(int x, int y)
{

    if (!drag)
        return;
    if (!drawing)
        return;

    lock_data();
    drawing->x += ((float)(x - drag_x)) / drawing->scale;
    drawing->y -= ((float)(y - drag_y)) / drawing->scale;
    unlock_data();
    drag_x = x;
    drag_y = y;

    drawing_sync();
}
Пример #13
0
      void Orderizer::load_data(const char* filename)
      {
        FILE* f = fopen(filename, "rb");
        if (f == NULL) error("Could not open %s for reading.", filename);
        lock_data();

        struct { char magic[4]; int ver; } hdr;
        if (fread(&hdr, sizeof(hdr), 1, f) != 1)
          error("Error reading %s", filename);

        if (hdr.magic[0] != 'H' || hdr.magic[1] != '2' || hdr.magic[2] != 'D' || hdr.magic[3] != 'O')
          error("File %s is not a Hermes2D Orderizer<Scalar> file.", filename);
        if (hdr.ver > 1)
          error("File %s -- unsupported file version.", filename);

#define read_array(array, type, n, c, what) \
  if (fread(&n, sizeof(int), 1, f) != 1) \
  error("Error reading the number of " what " from %s", filename); \
  lin_init_array(array, type, c, n); \
  if (fread(array, sizeof(type), n, f) != (unsigned) n) \
  error("Error reading " what " from %s", filename);

        read_array(verts, double3, nv, cv,  "vertices");
        read_array(tris,  int3,    nt, ct,  "triangles");
        read_array(edges, int3,    ne, ce,  "edges");
        read_array(lvert, int,     nl, cl1, "label vertices");

        lin_init_array(lbox, double2, cl3, nl);
        if (fread(lbox, sizeof(double2), nl, f) != (unsigned) nl)
          error("Error reading label bounding boxes from %s", filename);

        int* orders = new int[nl];
        if (fread(orders, sizeof(int), nl, f) != (unsigned) nl)
          error("Error reading element orders from %s", filename);

        lin_init_array(ltext, char*, cl2, nl);
        for (int i = 0; i < nl; i++)
          ltext[i] = labels[H2D_GET_H_ORDER(orders[i])][H2D_GET_V_ORDER(orders[i])];

        find_min_max();
        unlock_data();
        fclose(f);
      }
Пример #14
0
void CPSampleManagerImpl::set_data(CPSample_ID p_id, int p_sample, int16_t p_data, int p_channel) {

	SampleData *sd = _getsd(p_id);
#ifdef DEBUG_ENABLED
	ERR_FAIL_COND(!valid.has(sd));
#endif

	ERR_FAIL();
	lock_data(p_id);

	int sofs = sd->stereo ? 2 : 1;
	if (sd->is16) {
		int16_t *p = (int16_t *)sd->w.ptr();
		p[p_sample * sofs + p_channel] = p_data;
	} else {
		int8_t *p = (int8_t *)sd->w.ptr();
		p[p_sample * sofs + p_channel] = p_data;
	}

	unlock_data(p_id);
}
Пример #15
0
      void Linearizer::process_solution(MeshFunction<double>* sln, int item, double eps)
      {
        lock_data();
        Hermes::TimePeriod time_period;

        // initialization
        this->sln = sln;
        if(!user_xdisp)
          xdisp = new ZeroSolution(sln->get_mesh());
        if(!user_ydisp)
          ydisp = new ZeroSolution(sln->get_mesh());

        this->item = item;
        this->eps = eps;

        // get the component and desired value from item.
        if (item >= 0x40)
        {
          component = 1;
          item >>= 6;
        }
Пример #16
0
void Vectorizer::save_data(const char* filename)
{
  FILE* f = fopen(filename, "wb");
  if (f == NULL) error("Could not open %s for writing.", filename);
  lock_data();

  if (fwrite("H2DV\001\000\000\000", 1, 8, f) != 8 ||
      fwrite(&nv, sizeof(int), 1, f) != 1 ||
      fwrite(verts, sizeof(double4), nv, f) != nv ||
      fwrite(&nt, sizeof(int), 1, f) != 1 ||
      fwrite(tris, sizeof(int3), nt, f) != nt ||
      fwrite(&ne, sizeof(int), 1, f) != 1 ||
      fwrite(edges, sizeof(int3), ne, f) != ne ||
      fwrite(&nd, sizeof(int), 1, f) != 1 ||
      fwrite(dashes, sizeof(int2), nd, f) != nd)
  {
    error("Error writing data to %s", filename);
  }

  unlock_data();
  fclose(f);
}
Пример #17
0
bool FmMsg::insert(FmMsgQ_entry * src) {
	if (!strcmp(_name, src->dst)) {
		FmMsgEntry dst(*(src->data), OWNERSHIP);

		if (_cnt == _max) {
			_handle(src->data);
			return false;
		}

		while (!lock_data()); // wait for the lock.
		_buf.push(dst);
		unlock_data();

		++_cnt;

		_flag = true;
	} else {
		_flag = false;
	}

	return _flag;
}
Пример #18
0
void
shell_drag_stop(int x, int y)
{

    if (!drawing)
        return;
    lock_data();

    drawing->x += ((float)(x - drag_x)) / drawing->scale;
    drawing->y -= ((float)(y - drag_y)) / drawing->scale;

    append_undo_double((void *)(&(drawing->x)),
                       drawing->old.x, drawing->x, 1, OBJ_DRAWING, NULL);
    append_undo_double((void *)(&(drawing->y)),
                       drawing->old.y, drawing->y, 0, 0, NULL);
    unlock_data();
    drag_x = x;
    drag_y = y;

    drawing_sync();
    drag = 0;
    pointer_pop(0x1500 + POINTER_HAND);
}
Пример #19
0
int16_t CPSampleManagerImpl::get_data(CPSample_ID p_id, int p_sample, int p_channel){

	SampleData *sd=_getsd(p_id);
#ifdef DEBUG_ENABLED
	ERR_FAIL_COND_V(!valid.has(sd),0);
#endif

	ERR_FAIL_V(0);
	lock_data(p_id);

	int sofs = sd->stereo ? 2:1;
	uint16_t v=0;
	if (sd->is16) {
		int16_t *p=(int16_t*)sd->w.ptr();
		v=p[p_sample*sofs+p_channel];
	} else {
		int8_t *p=(int8_t*)sd->w.ptr();
		v=p[p_sample*sofs+p_channel];
	}

	unlock_data(p_id);

	return v;
}
Пример #20
0
void Linearizer::process_solution(MeshFunction* sln, int item, double eps, double max_abs,
                                  MeshFunction* xdisp, MeshFunction* ydisp, double dmult)
{
  lock_data();
  begin_time();

  // initialization
  this->sln = sln;
  this->item = item;
  this->eps = eps;
  this->xdisp = xdisp;
  this->ydisp = ydisp;
  this->dmult = dmult;
  nv = nt = ne = 0;
  del_slot = -1;

  if (!item) error("'item' cannot be zero.");
  get_gv_a_b(item, ia, ib);
  if (ib >= 6) error("Invalid 'item'.");

  disp = (xdisp != NULL || ydisp != NULL);
  if (disp && (xdisp == NULL || ydisp == NULL))
    error("Both displacement components must be supplied.");

  // estimate the required number of vertices and triangles
  Mesh* mesh = sln->get_mesh();
  int nn = mesh->get_num_elements();
  int ev = std::max(32 * nn, 10000);  // todo: check this
  int et = std::max(64 * nn, 20000);
  int ee = std::max(24 * nn, 7500);

  // check that displacement meshes are the same
  if (disp)
  {
    unsigned seq1 = mesh->get_seq();
    unsigned seq2 = xdisp->get_mesh()->get_seq();
    unsigned seq3 = ydisp->get_mesh()->get_seq();
    if (seq1 != seq2 || seq1 != seq3)
      error("Displacements must be defined on the same mesh as the solution.");
  }

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  info = (int4*) malloc(sizeof(int4) * cv);

  // initialize the hash table
  int size = 0x2000;
  while (size*2 < cv) size *= 2;
  hash_table = (int*) malloc(sizeof(int) * size);
  memset(hash_table, 0xff, sizeof(int) * size);
  mask = size-1;

  // select the linearization quadrature
  Quad2D *old_quad, *old_quad_x, *old_quad_y;
  old_quad = sln->get_quad_2d();
  sln->set_quad_2d(&quad_lin);
  if (disp) { old_quad_x = xdisp->get_quad_2d();
              old_quad_y = ydisp->get_quad_2d();
              xdisp->set_quad_2d(&quad_lin);
              ydisp->set_quad_2d(&quad_lin); }

  // create all top-level vertices (corresponding to vertex nodes), with
  // all parent-son relations preserved; this is necessary for regularization to
  // work on irregular meshes
  nn = mesh->get_max_node_id();
  int* id2id = new int[nn];
  memset(id2id, 0xff, sizeof(int) * nn);
  bool finished;
  do
  {
    finished = true;
    Node* node;
    for_all_vertex_nodes(node, mesh)
    {
      if (id2id[node->id] < 0 && node->ref != TOP_LEVEL_REF)
        if (node->p1 < 0)
          id2id[node->id] = get_vertex(node->id, node->id, node->x, node->y, 0);
        else if (id2id[node->p1] >= 0 && id2id[node->p2] >= 0)
          id2id[node->id] = get_vertex(id2id[node->p1], id2id[node->p2], node->x, node->y, 0);
        else
          finished = false;
    }
  }
  while (!finished);

  auto_max = (max_abs < 0.0);
  max = auto_max ? 0.0 : max_abs;

  // obtain the solution in vertices, estimate the maximum solution value
  Element* e;
  for_all_active_elements(e, mesh)
  {
    sln->set_active_element(e);
    sln->set_quad_order(0, item);
    scalar* val = sln->get_values(ia, ib);
    if (val == NULL) error("item not defined in the solution.");

    scalar *dx, *dy;
    if (disp)
    {
      xdisp->set_active_element(e);
      ydisp->set_active_element(e);
      xdisp->set_quad_order(0, FN_VAL);
      ydisp->set_quad_order(0, FN_VAL);
      dx = xdisp->get_fn_values();
      dy = ydisp->get_fn_values();
    }

    for (unsigned int i = 0; i < e->nvert; i++)
    {
      double f = getval(i);
      if (auto_max && finite(f) && fabs(f) > max) max = fabs(f);
      int id = id2id[e->vn[i]->id];
      verts[id][2] = f;

      if (disp)
      {
        verts[id][0] = e->vn[i]->x + dmult*realpart(dx[i]);
        verts[id][1] = e->vn[i]->y + dmult*realpart(dy[i]);
      }
    }
  }
Sint16 SampleManager_MemPool::get_data(Sample_ID p_id, int p_sample, int p_channel) {
	MemPool_Sample *smp;
	if (!(smp=get_sample(p_id)))
		return 0;
	
	ERR_FAIL_INDEX_V(p_sample,smp->size,0);
	ERR_FAIL_COND_V(p_channel<0,0);
	
	if (smp->stereo) {
		
		ERR_FAIL_COND_V(p_channel>1,0);
	} else {
		
		ERR_FAIL_COND_V(p_channel>0,0);
	}
	

	if (lock_data(p_id)) {
		return 0;
	}
	
	Sint16 res;
	
	if (smp->is_16bits) {
		
		Sint16 *ptr=(Sint16*)get_data( p_id );
		
		if (ptr==0) {
			unlock_data(p_id);
			ERR_FAIL_COND_V(ptr==0,0);
		}
		
		if (smp->stereo)
			p_sample*=2;
		p_sample+=p_channel;
		
		res=ptr[p_sample];
		
		
	} else {
		
		Sint8 *ptr=(Sint8*)get_data( p_id );
		
		if (ptr==0) {
			unlock_data(p_id);
			ERR_FAIL_COND_V(ptr==0,0);
		}
		
		if (smp->stereo)
			p_sample*=2;
		p_sample+=p_channel;
		
		res=ptr[p_sample];
		
		res<<=8;
	}
	unlock_data( p_id );
	

	return res;
}
void SampleManager_MemPool::set_data(Sample_ID p_id, int p_sample, Sint16 p_data,int p_channel) {
	
	MemPool_Sample *smp;
	if (!(smp=get_sample(p_id)))
		return;
	
	ERR_FAIL_COND( p_sample<-1 || (p_sample>smp->size+1));
	ERR_FAIL_COND(p_channel<0);

	if (smp->stereo) {
		
		ERR_FAIL_COND(p_channel>1);
	} else {
		
		ERR_FAIL_COND(p_channel>0);
	}
	
	AudioLock::begin();
	if (lock_data(p_id)) {
		
		AudioLock::end();
		return ;
	}
	
	
	if (smp->is_16bits) {
		
		Sint16 *ptr=(Sint16*)get_data( p_id );
		
		if (ptr==0) {
			unlock_data(p_id);
			AudioLock::end();
			ERR_FAIL_COND(ptr==0);
		}
		
		if (smp->stereo)
			p_sample*=2;
		p_sample+=p_channel;
		
		ptr[p_sample]=p_data;
		
		
	} else {
		
		Sint8 *ptr=(Sint8*)get_data( p_id );
		
		if (ptr==0) {
			unlock_data(p_id);
			AudioLock::end();
			ERR_FAIL_COND(ptr==0);
		}
		
		if (smp->stereo)
			p_sample*=2;
		p_sample+=p_channel;
		
		ptr[p_sample]=p_data>>8;

	}
	
	unlock_data( p_id );
	AudioLock::end();
	
	if ((p_sample>=0 && p_sample<smp->size) && (p_sample==(smp->size-1) ||  (smp->loop.type!=LOOP_NONE && p_sample==smp->loop.begin && smp->loop.begin<(smp->size-1))))
		fix_loop_end( p_id );
}
Пример #23
0
void Vectorizer::process_solution(MeshFunction* xsln, int xitem, MeshFunction* ysln, int yitem, double eps)
{
  // sanity check
  if (xsln == NULL || ysln == NULL) error("One of the solutions is NULL in Vectorizer:process_solution().");


  lock_data();
  TimePeriod cpu_time;

  // initialization
  this->xsln = xsln;
  this->ysln = ysln;
  this->xitem = xitem;
  this->yitem = yitem;
  this->eps = eps;
  nv = nt = ne = nd = 0;
  del_slot = -1;

  Mesh* meshes[2] = { xsln->get_mesh(), ysln->get_mesh() };
  if (meshes[0] == NULL || meshes[1] == NULL) {
    error("One of the meshes is NULL in Vectorizer:process_solution().");
  }

  Transformable* fns[2] = { xsln, ysln };
  Traverse trav;

  // estimate the required number of vertices and triangles
  // (based on the assumption that the linear mesh will be
  // about four-times finer than the original mesh).
  int nn = meshes[0]->get_num_elements() + meshes[1]->get_num_elements();
  int ev = std::max(32 * nn, 10000);
  int et = std::max(64 * nn, 20000);
  int ee = std::max(24 * nn, 7500);
  int ed = ee;

  lin_init_array(verts, double4, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(dashes, int2, cd, ed);

  info = (int4*) malloc(sizeof(int4) * cv);

  // initialize the hash table
  int size = 0x1000;
  while (size*2 < cv) size *= 2;
  hash_table = (int*) malloc(sizeof(int) * size);
  memset(hash_table, 0xff, sizeof(int) * size);
  mask = size-1;


  // select the linearization quadrature
  Quad2D *old_quad_x, *old_quad_y;
  old_quad_x = xsln->get_quad_2d();
  old_quad_y = ysln->get_quad_2d();

  xsln->set_quad_2d((Quad2D*) &quad_lin);
  ysln->set_quad_2d((Quad2D*) &quad_lin);

  if (!xitem) error("Parameter 'xitem' cannot be zero.");
  if (!yitem) error("Parameter 'yitem' cannot be zero.");
  get_gv_a_b(xitem, xia, xib);
  get_gv_a_b(yitem, yia, yib);
  if (xib >= 6) error("Invalid value of paremeter 'xitem'.");
  if (yib >= 6) error("Invalid value of paremeter 'yitem'.");

  max = 1e-10;
  trav.begin(2, meshes, fns);
  Element** e;
  while ((e = trav.get_next_state(NULL, NULL)) != NULL)
  {
    xsln->set_quad_order(0, xitem);
    ysln->set_quad_order(0, yitem);
    scalar* xval = xsln->get_values(xia, xib);
    scalar* yval = ysln->get_values(yia, yib);

    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      double fx = getvalx(i);
      double fy = getvaly(i);
      if (fabs(sqrt(fx*fx + fy*fy)) > max) max = fabs(sqrt(fx*fx + fy*fy));
    }
  }
  trav.finish();

  trav.begin(2, meshes, fns);
  // process all elements of the mesh
  while ((e = trav.get_next_state(NULL, NULL)) != NULL)
  {
    xsln->set_quad_order(0, xitem);
    ysln->set_quad_order(0, yitem);
    scalar* xval = xsln->get_values(xia, xib);
    scalar* yval = ysln->get_values(yia, yib);

    double* x = xsln->get_refmap()->get_phys_x(0);
    double* y = ysln->get_refmap()->get_phys_y(0);

    int iv[4];
    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      double fx = getvalx(i);
      double fy = getvaly(i);
      iv[i] = create_vertex(x[i], y[i], fx, fy);
    }

    // we won't bother calculating physical coordinates from the refmap if this is not a curved element
    curved = (e[0]->cm != NULL);

    // recur to sub-elements
    if (e[0]->is_triangle())
      process_triangle(iv[0], iv[1], iv[2], 0, NULL, NULL, NULL, NULL, NULL);
    else
      process_quad(iv[0], iv[1], iv[2], iv[3], 0, NULL, NULL, NULL, NULL, NULL);

    // process edges and dashes (bold line for edge in both meshes, dashed line for edge in one of the meshes)
    Trf* xctm = xsln->get_ctm();
    Trf* yctm = ysln->get_ctm();
    double r[4] = { -1.0, 1.0, 1.0, -1.0 };
    double ref[4][2] = { {-1.0,-1.0}, {1.0,-1.0}, {1.0,1.0}, {-1.0,1.0} };
    for (unsigned int i = 0; i < e[0]->nvert; i++)
    {
      bool bold = false;
      double px = ref[i][0];
      double py = ref[i][1];
      // for odd edges (1, 3) we check x coordinate after ctm transformation, if it's the same (1 or -1) in both meshes => bold
      if (i & 1) {
        if ((xctm->m[0]*px + xctm->t[0] == r[i]) && (yctm->m[0]*px + yctm->t[0] == r[i]))
          bold = true;
      }
      // for even edges (0, 4) we check y coordinate after ctm transformation, if it's the same (-1 or 1) in both meshes => bold
      else {
        if ((xctm->m[1]*py + xctm->t[1] == r[i]) && (yctm->m[1]*py + yctm->t[1] == r[i]))
          bold = true;
      }
      int j = e[0]->next_vert(i);
      // we draw a line only if both edges lies on the boundary or if the line is from left top to right bottom
      if (((e[0]->en[i]->bnd) && (e[1]->en[i]->bnd)) ||
         (verts[iv[i]][1] < verts[iv[j]][1]) ||
         (verts[iv[i]][1] == verts[iv[j]][1] && verts[iv[i]][0] < verts[iv[j]][0]))
      {
        if (bold)
          process_edge(iv[i], iv[j], e[0]->en[i]->marker);
        else
          process_dash(iv[i], iv[j]);
      }
    }
  }
  trav.finish();

  find_min_max();

  verbose("Vectorizer created %d verts and %d tris in %0.3g s", nv, nt, cpu_time.tick().last());
  //if (verbose_mode) print_hash_stats();
  unlock_data();

   // select old quadratrues
  xsln->set_quad_2d(old_quad_x);
  ysln->set_quad_2d(old_quad_y);

  // clean up
  ::free(hash_table);
  ::free(info);

}