view nonfree/gpc/octave-gpc.cc @ 0:6b33357c7561 octave-forge

Initial revision
author pkienzle
date Wed, 10 Oct 2001 19:54:49 +0000
parents
children 731e0bfdb40c
line wrap: on
line source

/*

Copyright (C) 2001 Rafael Laboissiere

This file is part of octave-gpc.

octave-gpc is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

octave-gpc is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with octave-gpc; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "octave-gpc.h"

// Registration of the octave_gpc_polygon object type.
DEFINE_OCTAVE_ALLOCATOR (octave_gpc_polygon);

DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_gpc_polygon, "gpc_polygon");

// Member function

void 
octave_gpc_polygon::print (ostream& os, bool pr_as_read_syntax = false) const
{
  os << "Variable is of type " <<  t_name << ".\n"
     << "Its members (accessible with the function gpc_get) are:\n";
  Octave_map m;
  gpc_to_map (polygon, &m);
  (octave_struct (m)).print (os);
}


// Utility function to check if an Octave object is a matrix with 2
// columns.  This is the basic type for x.vertices and x.indices,
// where x is of type gpc_polygon.

static
bool
assert_nx2_matrix (octave_value ov)
{
  if ( ! ov.is_matrix_type () )
    return false;
  if ( ov.columns () != 2 )
    return false;
  return true;
}

// gpc_polygon_free will free any C gpc_polygon structure initialized
// by the octave_gpc library (in C++).  For
void
octave_gpc_free_polygon (gpc_polygon* p)
{
  delete [] p->hole;
  for (int i = 0; i < p->num_contours; i++)
    delete [] p->contour[i].vertex;
  delete [] p->contour;
}

gpc_polygon*
get_gpc_pt (octave_value v)
{
  // Peek the representation and extract the data (i.e., the pointer
  // to the gpc_polygon stored in the octave variable).  This seems to
  // be the only way to do that with Octave 2.1
  const octave_value& rep = v.get_rep ();
  return ((const octave_gpc_polygon&) rep).polygon_value ();
}

void
map_to_gpc (Octave_map& m, gpc_polygon* p)
{

  Matrix vtx = m ["vertices"].matrix_value ();
  Matrix idx = m ["indices"].matrix_value ();
  ColumnVector hol = m ["hole"].column_vector_value ();
  int n = idx.rows ();

  p->num_contours = n;
  p->hole = new int [n];
  p->contour = new gpc_vertex_list [n];

  for (int i = 0; i < n; i++)
    {
      p->hole[i] = (int) hol (i);

      int j0 = (int) idx (i, 0) - 1;
      int m = (int) idx (i, 1) - j0;

      p->contour[i].num_vertices = m;
      p->contour[i].vertex = new gpc_vertex [m];

      for (int j = 0; j < m; j++)
	{
	  p->contour[i].vertex[j].x = vtx (j0 + j, 0);
	  p->contour[i].vertex[j].y = vtx (j0 + j, 1);
	}
    }
}

void 
gpc_to_map (gpc_polygon* p, Octave_map* map)
{
  int n = p->num_contours;
  ColumnVector hol (n);
  Matrix idx (n, 2);
  int m = 0;
  for (int i = 0; i < n; i++) 
    {
      hol (i) = p->hole[i];
      idx (i, 0) = m + 1;
      m += p->contour[i].num_vertices;
      idx (i, 1) = m;
    }
  Matrix vtx (m, 2);
  int j = 0;
  for (int i = 0; i < n; i++)
    {
      int m = p->contour[i].num_vertices;
      gpc_vertex* v = p->contour[i].vertex;
      for (int k = 0; k < m; k++)
	{
	  vtx (j, 0) = v[k].x;
	  vtx (j++, 1) = v[k].y;
	}
    }

  (*map) ["vertices"] = vtx;
  (*map) ["indices"] = idx;
  (*map) ["hole"] = hol;
}  
  
bool 
assert_gpc_polygon (Octave_map* m)
{
  if ( ! m->contains ("vertices") )
    {
      warning ("No vertices !");
      return false;
    }
  octave_value v = (*m) ["vertices"];
  if ( ! assert_nx2_matrix (v) )
    {
      warning ("assert_gpc_polygon: vertices member should be a "
	       "[n,2] matrix");
      	return false;
    }
  octave_value i;
  if ( ! m->contains ("indices") )
    {
      Matrix im (1, 2);
      im (0, 0) = (double) 1;
      im (0, 1) = (double) v.rows ();
      i = (*m) ["indices"] = im;
    }
  else
    {
      i = (*m) ["indices"];
      if ( ! assert_nx2_matrix (i) )
	{
	  warning ("assert_gpc_polygon: indices member should be a "
		   "[n,2] matrix");
	  return false;
	}
      Matrix im = i.matrix_value ();
      if ( im.column_max ().max () > v.rows ()
	   || im.column_min ().min () < 1 )
	{
	  warning ("assert_gpc_polygon: indices out of range");
	  return false;
	}
    }

  if ( ! m->contains ("hole") )
    {
      ColumnVector h (i.rows ());
      h.fill ((double) 0);
      (*m) ["hole"] = h;
    }
  else
    {
      octave_value h = (*m) ["hole"];
    
      if ( (! h.is_matrix_type () || h.columns () != 1)
	   && ! h.is_real_scalar () )
	{
	  warning ("assert_gpc_polygon: hole member should be a "
		   "column vector");
	  return false;
	}
      int n = h.rows ();
      if ( n != i.rows () )
	{
	  warning ("assert_gpc_polygon: hole member length should "
		   "be equal to the number of lines of indices member");
	  return false;
	}
      for (int i = 0; i < n; i++)
	if ( h.matrix_value () (i, 0) != 0
	     && h.matrix_value () (i, 0) != 1 )
	  {
	    warning ("assert_gpc_polygon: hole member elements should "
		     "be either 0 or 1");
	    return false;
	  }
    }
  return true;
}

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/