static void
mex_telepathy_channel_new_tf_channel (GObject      *source,
                                      GAsyncResult *result,
                                      gpointer      user_data)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);
  MexTelepathyChannelPrivate *priv = self->priv;

  MEX_DEBUG ("New TfChannel");

  priv->tf_channel = TF_CHANNEL (g_async_initable_new_finish (
                                   G_ASYNC_INITABLE (source), result, NULL));

  if (priv->tf_channel == NULL)
    {
      MEX_WARNING ("Failed to create channel");
      return;
    }

  MEX_DEBUG ("Adding timeout");
  priv->pipeline_timer = g_timeout_add_seconds (5,
                         mex_telepathy_channel_dump_pipeline,
                         self);

  g_signal_connect (priv->tf_channel, "fs-conference-added",
                    G_CALLBACK (mex_telepathy_channel_conference_added), self);

  g_signal_connect (priv->tf_channel, "content-added",
                    G_CALLBACK (mex_telepathy_channel_on_content_added), self);
}
static void
mex_telepathy_channel_on_contact_fetched (TpConnection     *connection,
                                          guint             n_contacts,
                                          TpContact *const *contacts,
                                          guint             n_failed,
                                          const TpHandle   *failed,
                                          const GError     *fetched_error,
                                          gpointer          user_data,
                                          GObject          *weak_object)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);

  int i = 0;

  if (self->priv->channel)
    {
      for (i = 0; i < n_contacts; ++i)
        {
          gchar *text;
          const gchar *alias;
          TpContact *current;
          GFile *file;

          // Get the contacts.
          current = contacts[i];

          // Connect to alias change signal.
          // Add the alias to the label.
          alias = tp_contact_get_alias (current);
          mx_label_set_text (MX_LABEL (self->priv->title_label),
                             alias);

          if (tp_channel_get_requested(self->priv->channel))
            text = g_strdup_printf ("Calling %s", alias);
          else
            text = g_strdup_printf ("Setting up call with %s", alias);
          mx_label_set_text (MX_LABEL (self->priv->busy_label), text);
          g_free (text);

          file = tp_contact_get_avatar_file (current);
          if (file)
            {
              gchar *filename = g_file_get_path (file);
              GError *error = NULL;
              MEX_DEBUG ("setting new avatar filename to %s", filename);
              mx_image_set_from_file (MX_IMAGE(self->priv->avatar_image),
                                      filename,
                                      &error);
              if (error)
                {
                  MEX_ERROR ("ERROR %s loading avatar from file %s\n",
                             error->message, filename);
                  g_clear_error (&error);
                }
              if (filename)
                g_free (filename);
            }
        }
    }
}
Esempio n. 3
0
static void
handle_new_source_plugin (MexTrackerPlugin *self, GrlMediaPlugin *plugin)
{
  GrlSupportedOps ops;
  GrlMetadataSource *meta = GRL_METADATA_SOURCE (plugin);
  const char *id;

  id = grl_media_plugin_get_id (plugin);
  if (g_strcmp0 (id,"grl-tracker") != 0)
    {
      MEX_DEBUG ("Attempting to use the media explorer tracker plugin "
                 "but grilo tracker plugin not loaded. "
                 "You may not see any content!");
      return;
    }

  ops = grl_metadata_source_supported_operations (meta);
  if ((ops & GRL_OP_QUERY) == 0)
    return;

  grl_media_source_notify_change_start (GRL_MEDIA_SOURCE (plugin), NULL);

  add_model (self, plugin, MEX_TRACKER_CATEGORY_VIDEO);
  add_model (self, plugin, MEX_TRACKER_CATEGORY_IMAGE);
  add_model (self, plugin, MEX_TRACKER_CATEGORY_MUSIC);
}
Esempio n. 4
0
static void
mex_surface_player_init (MexSurfacePlayer *self)
{
  MEX_DEBUG ("init");

  self->priv = SURFACE_PLAYER_PRIVATE (self);

  clutter_gst_player_init (CLUTTER_GST_PLAYER (self));
}
static void
mex_telepathy_channel_on_content_added (TfChannel *channel,
                                        TfContent *content,
                                        gpointer   user_data)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);
  MexTelepathyChannelPrivate *priv = self->priv;
  GstPad *srcpad, *sinkpad;
  FsMediaType mtype;
  GstElement *element;
  GstStateChangeReturn ret;

  MEX_DEBUG ("Content added");

  g_object_get (content,
                "sink-pad", &sinkpad,
                "media-type", &mtype,
                NULL);

  switch (mtype)
    {
    case FS_MEDIA_TYPE_AUDIO:
      MEX_DEBUG ("Audio content added");
      element = gst_parse_bin_from_description (
        "autoaudiosrc ! audioresample ! audioconvert ! volume name=micvolume", TRUE, NULL);
      priv->outgoing_mic = element;
      priv->mic_volume = gst_bin_get_by_name (GST_BIN (priv->outgoing_mic), "micvolume");
      break;
    case FS_MEDIA_TYPE_VIDEO:
      MEX_DEBUG ("Video content added");
      element = mex_telepathy_channel_setup_video_source (self, content);
      break;
    default:
      MEX_WARNING ("Unknown media type");
      g_object_unref (sinkpad);
      return;
    }

  g_signal_connect (content, "src-pad-added",
                    G_CALLBACK (mex_telepathy_channel_on_src_pad_added), self);

  gst_bin_add (GST_BIN (priv->pipeline), element);
  srcpad = gst_element_get_pad (element, "src");

  if (GST_PAD_LINK_FAILED (gst_pad_link (srcpad, sinkpad)))
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Couldn't link source pipeline !?");
      return;
    }

  ret = gst_element_set_state (element, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE)
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("source pipeline failed to start!?");
      return;
    }

  g_object_unref (srcpad);
  g_object_unref (sinkpad);
}
static void
mex_telepathy_channel_on_src_pad_added (TfContent *content,
                                        TpHandle   handle,
                                        FsStream  *stream,
                                        GstPad    *pad,
                                        FsCodec   *codec,
                                        gpointer   user_data)
{
  MexTelepathyChannel *self = MEX_TELEPATHY_CHANNEL (user_data);
  MexTelepathyChannelPrivate *priv = self->priv;

  gchar *cstr = fs_codec_to_string (codec);
  FsMediaType mtype;
  GstPad *sinkpad;
  GstElement *element;
  GstStateChangeReturn ret;

  /* Upon pad added, clear the "in progress" box+padding */
  clutter_actor_hide (CLUTTER_ACTOR (priv->busy_box));
  clutter_actor_show (CLUTTER_ACTOR (priv->full_frame) );

  MEX_DEBUG ("New src pad: %s", cstr);
  g_object_get (content, "media-type", &mtype, NULL);

  switch (mtype)
    {
    case FS_MEDIA_TYPE_AUDIO:
      element = gst_parse_bin_from_description (
        "audioconvert ! audioresample ! audioconvert ! autoaudiosink",
        TRUE, NULL);
      break;
    case FS_MEDIA_TYPE_VIDEO:
      element = priv->incoming_sink;
      break;
    default:
      MEX_WARNING ("Unknown media type");
      return;
    }

  if (!gst_bin_add (GST_BIN (priv->pipeline), element))
    {
      MEX_WARNING ("Failed to add sink element to pipeline");
    }
  sinkpad = gst_element_get_pad (element, "sink");
  ret = gst_element_set_state (element, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE)
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Failed to start tee sink pipeline !?");
      return;
    }

  if (GST_PAD_LINK_FAILED (gst_pad_link (pad, sinkpad)))
    {
      tp_channel_close_async (TP_CHANNEL (priv->channel), NULL, NULL);
      MEX_WARNING ("Couldn't link sink pipeline !?");
      return;
    }

  g_object_unref (sinkpad);

  /* Start in FULL mode */
  mex_telepathy_channel_set_tool_mode (self, TOOL_MODE_FULL, 100);
}
void CommandComputeMatches(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
  // Expected Input:
  //  cmd
  //  class handle
  //  samplePtsXfmd       ~ sample points             (3 x nSamps double)
  //  samplePtsCov        ~ sample point covariances  (3 x 3 x nSamps double)
  //  matchDatumsInit     ~ initial match datums      (1 x nSamps int32)   [optional]
  // 
  // Output:
  //  MatchPts3D      ~ 3D match points (in camera coords)    (3 x nSamps double)
  //  MatchNorms3D    ~ 3D match norms  (in camera coords)    (3 x nSamps double)  [optional]
  //  matchDatums     ~ final match datums                    (1 x nSamps int32)   [optional]
  // 

  // Check parameters
  if ((nlhs < 1 || nlhs > 3) || (nrhs < 4 || nrhs > 5))
  {
    MEX_ERROR("ComputeMatches: requires 1 or 3 outputs, 4 or 5 inputs.");
  }

  // Get the class instance from the second input
  mexInterface_AlgPDTree_MLP_Mesh& obj =
    *convertMat2Ptr<mexInterface_AlgPDTree_MLP_Mesh>(prhs[1]);

  algPDTree_MLP_Mesh& alg = *obj.pAlg;


  //--- Inputs ---//

  MEX_DEBUG("Parsing Inputs...\n");

  // Parse Samples
  MEX_DEBUG(" ...samplePts\n");
  Parse3DVectorArray_Double(prhs[2], obj.samplePtsXfmd);

  // Parse Sample Covariances
  MEX_DEBUG(" ...sampleCov\n");
  ParseMatrixArray3x3_Double(prhs[3], obj.sampleCovXfmd);
  if (obj.sampleCovXfmd.size() != obj.samplePtsXfmd.size())
  {
    MEX_ERROR("ERROR: number of covariances does not equal number of samples");
  }

  // Parse Match Datum Initializers
  bool bDatumsInitialized = false;
  if (nrhs >= 5)
  {    
    MEX_DEBUG(" ...matchDatumsInit\n");
    ParseVector_Int(prhs[4], obj.matchDatums);
    bDatumsInitialized = true;
  }

  MEX_DEBUG(" ...done\n");


  //--- Computation ---//

  obj.nSamples = obj.samplePtsXfmd.size();
  obj.matchPts.SetSize(obj.nSamples);
  obj.matchNorms.SetSize(obj.nSamples);
  obj.matchDatums.SetSize(obj.nSamples);
  obj.matchErrors.SetSize(obj.nSamples);

  if (!bDatumsInitialized)
  {
    // initialize match datums with accelerated approximate search
    for (unsigned int i = 0; i < obj.nSamples; i++)
    {
      obj.matchDatums[i] = obj.pTree->FastInitializeProximalDatum(
        obj.samplePtsXfmd[i], obj.matchPts[i]);
    }
  }

  // compute matches
  obj.ComputeMatches();


  //--- Outputs ---//

  unsigned int nSamps = obj.nSamples;

  // outputs 1 & 2: match points and normals
  plhs[0] = mxCreateDoubleMatrix(3, nSamps, mxREAL);
  plhs[1] = mxCreateDoubleMatrix(3, nSamps, mxREAL);
  double *matchPts = mxGetPr(plhs[0]);
  double *matchNorms = mxGetPr(plhs[1]);
  for (unsigned int i = 0; i < nSamps; i++)
  {
    (*matchPts) = obj.matchPts[i].Element(0);
    matchPts++;
    (*matchPts) = obj.matchPts[i].Element(1);
    matchPts++;
    (*matchPts) = obj.matchPts[i].Element(2);
    matchPts++;

    (*matchNorms) = obj.matchNorms[i].Element(0);
    matchNorms++;
    (*matchNorms) = obj.matchNorms[i].Element(1);
    matchNorms++;
    (*matchNorms) = obj.matchNorms[i].Element(2);
    matchNorms++;
  }

  // output 3: match datums
  if (nlhs >= 3)
  {
    plhs[2] = mxCreateNumericMatrix(nSamps, 1, mxINT32_CLASS, mxREAL);
    int *matchDatums = static_cast<int*> (mxGetData(plhs[2]));
    for (unsigned int i = 0; i < nSamps; i++)
    {
      (*matchDatums) = obj.matchDatums[i];
      matchDatums++;
    }
  }

}
void CommandInitialize(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
  // Expected Input:
  //  cmd
  //  class handle
  //  mesh
  //    V ~ 3D vertex positions     (3 x Nv double)
  //    T ~ triangle vertex indices (3 x Nt integer)
  //    N ~ triangle normals        (3 x Nt double)
  //  mesh noise model (optional)
  //    Tcov ~ triangle covariances (3 x 3 x Nt double)
  //  

  std::stringstream ss;

  // Get the class instance from the second input
  mexInterface_AlgPDTree_MLP_Mesh& obj =
    *convertMat2Ptr<mexInterface_AlgPDTree_MLP_Mesh>(prhs[1]);

  // Check parameters
  if (nlhs != 0 || nrhs < 5 || nrhs > 6 )
  {
    MEX_ERROR("Cmd Initialize: requires 0 outputs, 5-6 inputs.");
  }


  //--- Inputs ---//

  MEX_DEBUG("Parsing Inputs...\n");

  // Parse Mesh  
  //vctDynamicVector<vct3> V;
  //vctDynamicVector<vctInt3> T;
  //vctDynamicVector<vct3> Tn;
  MEX_DEBUG(" ...V\n");
  Parse3DVectorArray_Double(prhs[2], obj.V);
  MEX_DEBUG(" ...T\n");
  Parse3DVectorArray_Int(prhs[3], obj.T);
  MEX_DEBUG(" ...N\n");
  Parse3DVectorArray_Double(prhs[4], obj.Tn);
  if (nrhs >= 6)
  {
    MEX_DEBUG(" ...Tcov\n");    
    ParseMatrixArray3x3_Double(prhs[5], obj.TriangleCov);
    unsigned int numT = obj.T.size();
    if (obj.TriangleCov.size() != numT)
    {
      MEX_ERROR("ERROR: number of triangle covariances does not equal number of triangles");
    }
    // compute eigenvalues of triangle covariances
    obj.TriangleCovEig.SetSize(numT);
    vct3x3 dummyMat;
    for (unsigned int i = 0; i < numT; i++)
    {
      ComputeCovEigenDecomposition_NonIter(obj.TriangleCov[i], obj.TriangleCovEig[i], dummyMat);
    }
  }
  else
  {
    obj.TriangleCov.SetSize(obj.T.size());
    obj.TriangleCovEig.SetSize(obj.T.size());
    obj.TriangleCov.SetAll(vct3x3(0.0));
    obj.TriangleCovEig.SetAll(vct3(0.0));
  }
  MEX_DEBUG(" ...done\n");


  //--- Processing ---//

  // build mesh
  MEX_DEBUG("Building mesh...\n");
  cisstMesh *pMesh = new cisstMesh();
  pMesh->LoadMesh(&obj.V, &obj.T, &obj.Tn);
  if (pMesh->NumVertices() == 0)
  {
    MEX_ERROR("ERROR: Build mesh failed\n");
  }
  // set mesh noise model
  pMesh->TriangleCov = obj.TriangleCov;
  pMesh->TriangleCovEig = obj.TriangleCovEig;
  // build covariance tree
  int    nThresh = 5;       // Cov Tree Params
  double diagThresh = 5.0;  //  ''
  MEX_DEBUG("Building mesh covariance tree...\n");
  obj.pTree = new PDTree_Mesh(*pMesh, nThresh, diagThresh);
  //PDTree_Mesh *pPDTree = new PDTree_Mesh(*pMesh, nThresh, diagThresh);  
  if (nrhs >= 6)
  { // compute the node noise models
    obj.pTree->ComputeNodeNoiseModels();
  }
  ss.str("");
  ss << "Tree built:  NNodes = " << obj.pTree->NumNodes() << "  NDatums = "
    << obj.pTree->NumData() << "  TreeDepth = " << obj.pTree->TreeDepth() << "\n";
  MEX_DEBUG(ss.str());

  // create & initialize algorithm
  if (obj.pAlg)
  {
    delete obj.pAlg;
    obj.pAlg = NULL;
  }
  obj.pAlg = new algPDTree_MLP_Mesh(obj.pTree);
}
Esempio n. 9
0
/**
 * mex_init_load_plugins:
 *
 * Load the Grilo plugins.
 */
static void
mex_init_load_grilo_plugins (void)
{
  GrlPluginRegistry *registry;
  GError *error = NULL;
  gchar *settings;

  registry = grl_plugin_registry_get_default ();

  settings = mex_settings_find_config_file (mex_settings_get_default (),
                                            "grilo-system.conf");
  if (settings)
    grl_plugin_registry_add_config_from_file (registry, settings, NULL);
  g_free (settings);


  settings = mex_settings_find_config_file (mex_settings_get_default (),
                                            "mex.conf");
  /* Load plugins */

  if (settings)
    {
      GKeyFile *mex_conf;
      gchar **enabled_plugins;

      mex_conf = g_key_file_new ();

      g_key_file_load_from_file (mex_conf,
                                 settings,
                                 G_KEY_FILE_NONE,
                                 NULL);

      enabled_plugins = g_key_file_get_string_list (mex_conf,
                                                    "grilo-plugins",
                                                    "enabled",
                                                    NULL,
                                                    NULL);
      g_key_file_free (mex_conf);

      if (enabled_plugins)
        {
          gint i;

          for (i=0; enabled_plugins[i]; i++)
            {
              if (!grl_plugin_registry_load_by_id (registry,
                                                   enabled_plugins[i],
                                                   &error))
                {
                  g_warning ("Tried to load specified grilo plugin: %s but failed: %s",
                             enabled_plugins[i],
                             (error) ? error->message : "");

                  if (error)
                    g_clear_error (&error);
                }
              else
                {
                  MEX_DEBUG ("Loaded grilo plugin: %s plugin",
                             enabled_plugins[i]);
                }
            }
          g_strfreev (enabled_plugins);
        }
      else
        {
          MEX_DEBUG ("No enabled plugins in mex.conf, loading default plugins");
          grilo_load_default_plugins (registry);
        }
      g_free (settings);
    }
  else
    {
      MEX_DEBUG ("No mex.conf found, loading default plugins");
      grilo_load_default_plugins (registry);
    }

}
void CommandComputeMatches(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
  // Expected Input:
  //  cmd
  //  class handle
  //  samplePtsXfmd       ~ 2D sample points
  //  sampleNormsXfmd     ~ 2D sample orientations
  //  sigma2              ~ position variances
  //  k                   ~ orientation concentrations  
  //  matchDatumsInit     ~ initial match datums [optional]
  //  match_ThetaMax      ~ maximum permitted orientation error for a match [optional]
  // 
  // Output:
  //  MatchPts2D        ~ 2D match points (in image coords)     (2 x numSamps double)  
  //  MatchNorms2D      ~ 2D match norms  (in image coords)     (2 x numSamps double)
  //  MatchDatums       ~ match datums                          (numSamps int32)  (optional)
  //  PermittedMatches  ~ permitted matches (i.e. permitted if theta < thetaMax)  (numSamps logical) (optional)
  //

  // Check parameters
  if ((nlhs < 2 || nlhs > 4) || (nrhs < 6 || nrhs > 8))
  {
    MEX_ERROR("ComputeMatches: requires 2 to 4 outputs, 6 to 8 inputs.");
  }

  // Get the class instance from the second input
  mexInterface_Alg2D_DirPDTree_vonMises_Edges& obj =
    *convertMat2Ptr<mexInterface_Alg2D_DirPDTree_vonMises_Edges>(prhs[1]);

  alg2D_DirPDTree_vonMises_Edges& alg = *obj.pAlg;


  //--- Inputs ---//

  MEX_DEBUG("Parsing Inputs...\n");

  // Parse Samples
  //vctDynamicVector<vct2>    samplePts;
  //vctDynamicVector<vct2>    sampleNorms;
  MEX_DEBUG(" ...samplePts\n");
  Parse2DVectorArray_Double(prhs[2], obj.samplePtsXfmd);
  MEX_DEBUG(" ...sampleNorms\n");
  Parse2DVectorArray_Double(prhs[3], obj.sampleNormsXfmd);

  // Parse Noise Model  
  MEX_DEBUG(" ...sigma2\n");
  vctDynamicVector<double> sigma2;
  ParseVector_Double(prhs[4], sigma2);  
  if (sigma2.size() == 1)
  {
    obj.sigma2.SetSize(obj.samplePtsXfmd.size());
    obj.sigma2.SetAll(sigma2[0]);
  }
  else
  {
    if (sigma2.size() != obj.samplePtsXfmd.size())
    {
      MEX_ERROR("Invalid size sigma2");
    }
    obj.sigma2 = sigma2;
  }
  MEX_DEBUG(" ...k\n");
  vctDynamicVector<double> k;
  ParseVector_Double(prhs[5], k);
  if (k.size() == 1)
  {
    obj.k.SetSize(obj.samplePtsXfmd.size());
    obj.k.SetAll(k[0]);
  }
  else
  {
    if (k.size() != obj.samplePtsXfmd.size())
    {
      MEX_ERROR("Invalid size k");
    }
    obj.k = k;
  }

  // Parse Match Datum Initializers
  bool bDatumsInitialized = false;
  if (nrhs >= 7)
  {
    MEX_DEBUG(" ...matchDatumsInit\n");
    if (!mxIsEmpty(prhs[6]))
    {
      ParseVector_Int(prhs[6], obj.matchDatums);
      bDatumsInitialized = true;
    }
  }

  // Parse match_MaxTheta
  if (nrhs >= 8)
  {
    MEX_DEBUG(" ...match_MaxTheta\n");
    ParseDouble(prhs[7], obj.pAlg->dThetaMax);
    //ParseDouble(prhs[7], obj.match_ThetaMax);
  }
  else
  {
    obj.pAlg->dThetaMax = cmnPI;    // default
    //obj.match_ThetaMax = cmnPI;   // default
  }

  MEX_DEBUG(" ...done\n");


  //--- Computation ---//

  obj.nSamples = obj.samplePtsXfmd.size();

  obj.matchPts.SetSize(obj.nSamples);
  obj.matchNorms.SetSize(obj.nSamples);
  obj.matchDatums.SetSize(obj.nSamples);
  obj.matchErrors.SetSize(obj.nSamples);
  obj.matchPermitted.SetSize(obj.nSamples);
  
  if (!bDatumsInitialized)
  {
    // initialize match datums with accelerated approximate search
    // Note: since this is a position-only initialization, there
    //       may be many non-permitted matches in the initialization;
    //       for these matches, the initialization will not have helped
    for (unsigned int i = 0; i < obj.nSamples; i++)
    {
      obj.matchDatums[i] = obj.pDirTree->FastInitializeProximalDatum(
        obj.samplePtsXfmd[i], obj.sampleNormsXfmd[i],
        obj.matchPts[i], obj.matchNorms[i]);
    }
  }

  // initialize all permitted matches to false
  obj.matchPermitted.SetAll(false);
  //// initialize permitted match flag
  //obj.matchPermitted.SetAll(false);
  //double theta;
  //for (unsigned int i = 0; i < obj.nSamples; i++)
  //{
  //  theta = acos( vctDotProduct(obj.sampleNormsXfmd[i], obj.matchNorms[i]) );
  //  if (theta > obj.pAlg->dThetaMax)
  //  {
  //    obj.matchPermitted[i] = false;
  //  }
  //  else
  //  {
  //    obj.matchPermitted[i] = true;
  //  }
  //}

  // compute matches
  obj.ComputeMatches();


  //--- Outputs ---//

  unsigned int nSamps = obj.nSamples;

  // outputs 1 & 2: 2D match points and normals
  plhs[0] = mxCreateDoubleMatrix(2, nSamps, mxREAL);
  plhs[1] = mxCreateDoubleMatrix(2, nSamps, mxREAL);
  double *matchPts = mxGetPr(plhs[0]);
  double *matchNorms = mxGetPr(plhs[1]);
  for (unsigned int i = 0; i < nSamps; i++)
  {
    (*matchPts) = obj.matchPts[i].Element(0);
    matchPts++;
    (*matchPts) = obj.matchPts[i].Element(1);
    matchPts++;

    (*matchNorms) = obj.matchNorms[i].Element(0);
    matchNorms++;
    (*matchNorms) = obj.matchNorms[i].Element(1);
    matchNorms++;
  }

  // output 3: match datums
  if (nlhs >= 3)
  {
    plhs[2] = mxCreateNumericMatrix(1, nSamps, mxINT32_CLASS, mxREAL);
    int *matchDatums = static_cast<int*> (mxGetData(plhs[2]));
    for (unsigned int i = 0; i < nSamps; i++)
    {
      (*matchDatums) = obj.matchDatums[i];
      matchDatums++;
    }
  }

  // output 4: permitted matches
  if (nlhs >= 4)
  {
    plhs[3] = mxCreateLogicalMatrix(1, nSamps);
    mxLogical *matchPerm = mxGetLogicals(plhs[3]);
    //bool *matchDatums = static_cast<bool*> (mxGetData(plhs[4]));
    for (unsigned int i = 0; i < nSamps; i++)
    {
      (*matchPerm) = obj.matchPermitted[i];
      matchPerm++;
    }
  }
}
void CommandInitialize(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
  // Expected Input:
  //  cmd
  //  class handle
  //  edgesV1         ~ first vertices of 2D edges      (in image coords)
  //  edgesV2         ~ second vertices of 2D edges     (in image coords)
  //  edgesNorm       ~ 2D edge normals                 (in image coords)
  //

  std::stringstream ss;

  // Get the class instance from the second input
  mexInterface_Alg2D_DirPDTree_vonMises_Edges& obj =
    *convertMat2Ptr<mexInterface_Alg2D_DirPDTree_vonMises_Edges>(prhs[1]);

  // Check parameters
  if (nlhs != 0 || nrhs != 5)
  {
    MEX_ERROR("Cmd Initialize: requires 0 outputs, 5 inputs.");
  }


  //--- Inputs ---//

  MEX_DEBUG("Parsing Inputs...\n");

  // Parse 2D Edges
  //vctDynamicVector<vct2> edgesV1;
  //vctDynamicVector<vct2> edgesV2;
  //vctDynamicVector<vct2> edgesNorm;

  MEX_DEBUG(" ...edgesV1\n");
  Parse2DVectorArray_Double(prhs[2], obj.edgesV1);
  MEX_DEBUG(" ...edgesV2\n");
  Parse2DVectorArray_Double(prhs[3], obj.edgesV2);
  MEX_DEBUG(" ...edgesNorm\n");
  Parse2DVectorArray_Double(prhs[4], obj.edgesNorm);

  MEX_DEBUG(" ...done\n");


  //--- Processing ---//

  // build 2D edge covariance tree
  int nThresh = 6;
  double diagThresh = 0.0;
  bool bUseOBB = false;
  //bool bUseOBB = true;    // note: OBB's are not fully implemented for the 2D case (check the fast initialize search routine)
  obj.pDirTree = new DirPDTree2D_Edges(
    obj.edgesV1, obj.edgesV2, obj.edgesNorm,
    nThresh, diagThresh, bUseOBB);

  // create & initialize algorithm
  if (obj.pAlg)
  {
    delete obj.pAlg;
    obj.pAlg = NULL;
  }
  obj.pAlg = new alg2D_DirPDTree_vonMises_Edges(obj.pDirTree);

}