bool R3DSurfaceGenProcess::runSurfaceGenProcess(R3DProject::Surface *pSurface)
{
	R3DProject *pProject = R3DProject::getInstance();
	R3DProjectPaths paths;
	if(!pProject->getProjectPathsSrf(paths, pSurface))
		return false;
	pSurface_ = pSurface;

	beginTime_ = wxDateTime::UNow();


#if wxCHECK_VERSION(2, 9, 0)
	env_.cwd = paths.absoluteProjectPath_;

	// Set PATH/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH environment variable
#if defined(R3D_WIN32)
	wxString envVarName(wxT("PATH"));
#elif defined(R3D_MACOSX)
	wxString envVarName(wxT("DYLD_LIBRARY_PATH"));
#else
	wxString envVarName(wxT("LD_LIBRARY_PATH"));
#endif

	wxEnvVariableHashMap envVars;
	if(wxGetEnvMap(&envVars))
	{
		wxString concatPaths;
		const wxArrayString &exePaths = R3DExternalPrograms::getInstance().getAllPaths();
		for(size_t i = 0; i < exePaths.GetCount(); i++)
		{
			const wxString &curPath = exePaths[i];

			if(!concatPaths.IsEmpty())
#if defined(R3D_WIN32)
				concatPaths.Append(wxT(";"));
#else
				concatPaths.Append(wxT(":"));
#endif

			concatPaths.Append(curPath);
		}
		wxEnvVariableHashMap::iterator iter = envVars.find(envVarName);
		if(iter != envVars.end())
		{
			wxString val = iter->second;
			if(!val.IsEmpty())
#if defined(R3D_WIN32)
				val.Append(wxT(";"));
#else
				val.Append(wxT(":"));
#endif
			val.Append(concatPaths);
			envVars[envVarName] = val;
		}
		else
		{
			envVars[envVarName] = concatPaths;
		}
		env_.env = envVars;
	}
#endif

	cmds_.Clear();
	progressTexts_.Clear();

	wxString relativeSurfacePath(paths.relativeSurfacePath_.c_str(), wxConvLibc);
	wxString relativeSurfaceFilename;		// Used for texturing

	if(pSurface->surfaceType_ == R3DProject::STPoissonRecon)
	{
		wxString poissonReconExe = R3DExternalPrograms::getInstance().getPoissonReconPath();
		wxString surfaceTrimmerExe = R3DExternalPrograms::getInstance().getSurfaceTrimmerPath();
		wxString texreconExe = R3DExternalPrograms::getInstance().getTexReconPath();

		wxString poissonReconCmd = poissonReconExe + wxT(" --in ") + wxString(paths.relativeDenseModelName_.c_str(), wxConvLibc)
			+ wxT(" --out ") + relativeSurfacePath + wxT("/model_surface.ply")
			+ wxString::Format(wxT(" --depth %d --pointWeight %g --samplesPerNode %g"), 
			pSurface->poissonDepth_, pSurface->poissonPointWeight_, pSurface->poissonSamplesPerNode_);
		if(pSurface->poissonTrimThreshold_ > 0)
			poissonReconCmd.Append(wxT(" --density"));
		poissonReconCmd.Append(wxT(" --verbose"));
		cmds_.Add(poissonReconCmd);
		progressTexts_.Add(wxT("Generating surface (PoissonRecon)"));
		wxString surfaceFilename(wxT("model_surface.ply"));

		if(pSurface->poissonTrimThreshold_ > 0)
		{
			cmds_.Add(surfaceTrimmerExe + wxT(" --in ") + relativeSurfacePath + wxT("/model_surface.ply ") 
				+ wxString::Format(wxT("--trim %g"), pSurface->poissonTrimThreshold_)
				+ wxT(" --out ") + relativeSurfacePath + wxT("/model_surface_trim.ply"));
			progressTexts_.Add(wxT("Trimming surface"));
			surfaceFilename = wxT("model_surface_trim.ply");
		}

		// Store for later, will either be overwritten (texture case) or used as input (colorizing vertices case)
		pSurface->finalSurfaceFilename_ = surfaceFilename;

		if(pSurface->colorizationType_ == R3DProject::CTTextures)
		{
			wxFileName surfaceFN(relativeSurfacePath, surfaceFilename);
			relativeSurfaceFilename = surfaceFN.GetFullPath();

			pSurface->finalSurfaceFilename_ = wxT("model_surface_text.obj");
		}
	}
	else if(pSurface->surfaceType_ == R3DProject::STFSSRecon)
	{
		wxString fssReconExe = R3DExternalPrograms::getInstance().getFSSReconPath();
		wxString meshcleanExe = R3DExternalPrograms::getInstance().getMeshCleanPath();

		wxString surfaceModelName(wxT("surface_model.ply"));
		wxString cleanedSurfaceModelName(wxT("surface_clean_model.ply"));
		wxFileName surfaceModelFN(wxString(paths.relativeSurfacePath_.c_str(), wxConvLibc), surfaceModelName);
		wxFileName cleanedSurfaceModelFN(wxString(paths.relativeSurfacePath_.c_str(), wxConvLibc), cleanedSurfaceModelName);

		cmds_.Add(fssReconExe + wxString::Format(wxT(" --scale-factor=%g --refine-octree=%d "),
			pSurface->fssrScaleFactorMultiplier_, pSurface->fssrRefineOctreeLevels_)
			+ wxString(paths.relativeDenseModelName_.c_str(), wxConvLibc)
			+ wxT(" ")
			+ surfaceModelFN.GetFullPath());
		progressTexts_.Add(wxT("Generating surface (FSSR)"));

		cmds_.Add(meshcleanExe + wxString::Format(wxT(" --threshold=%g --component-size=%d "),
			pSurface->fssrConfidenceThreshold_, pSurface->fssrMinComponentSize_)
			+ surfaceModelFN.GetFullPath()
			+ wxT(" ")
			+ cleanedSurfaceModelFN.GetFullPath());
		progressTexts_.Add(wxT("Cleaning mesh (FSSR)"));

		relativeSurfaceFilename = cleanedSurfaceModelFN.GetFullPath();

		// Used only in case of colored vertices
		pSurface->finalSurfaceFilename_ = cleanedSurfaceModelName;
	}

	if(pSurface->colorizationType_ == R3DProject::CTTextures)
	{
		wxString texreconExe = R3DExternalPrograms::getInstance().getTexReconPath();

		wxString texreconCmd(texreconExe + wxT(" "));
		if(pSurface->textGeometricVisibilityTest_ == false)
			texreconCmd += wxT("--skip_geometric_visibility_test ");
		if(pSurface->textGlobalSeamLeveling_ == false)
			texreconCmd += wxT("--skip_global_seam_leveling ");
		if(pSurface->textLocalSeamLeveling_ == false)
			texreconCmd += wxT("--skip_local_seam_leveling ");
		if(pSurface->textOutlierRemovalType_ == 1)
			texreconCmd += wxT("--outlier_removal=gauss_clamping ");
		if(pSurface->textOutlierRemovalType_ == 2)
			texreconCmd += wxT("--outlier_removal=gauss_damping ");
		texreconCmd += wxT("--no_intermediate_results ");
		texreconCmd += wxString(paths.relativeMVESceneDir_.c_str(), wxConvLibc)
			+ wxT("::undistorted ")
			+ relativeSurfaceFilename + wxT(" ")
			+ relativeSurfacePath + wxT("/model_surface_text");

		cmds_.Add(texreconCmd);
		progressTexts_.Add(wxT("Generating texture (texrecon)"));

		pSurface->finalSurfaceFilename_ = wxT("model_surface_text.obj");
	}
	else if(pSurface->colorizationType_ == R3DProject::CTColoredVertices)
	{
		// No external program, this case is handled in Regard3DMainFrame::OnSurfaceGenFinished
	}

	runSingleCommand();

	return (processId_ > 0);
}
ExprNode *
ElemDDLPartitionSystem::bindNode(BindWA * /*pBindWA*/)
{
  //
  // location
  //
  ComLocationName defaultLocName;  // empty object

  if (getLocationName().isNull())
    //
    // location clause not specified (only allowed for primary partition)
    //
    guardianLocation_ =
      defaultLocName.getGuardianFullyQualifiedName();
  else  // LOCATION clause was specified
  {
    ComLocationName locName;         // empty object
    switch (getLocationNameType())
    {
    case ElemDDLLocation::LOCATION_GUARDIAN_NAME :
      locName.copy(getLocationName(),
                   ComLocationName::GUARDIAN_LOCATION_NAME_FORMAT);
      if (NOT locName.isValid())
      {
        // Illegal location name format.
        *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName());
        guardianLocation_ =
          defaultLocName.getGuardianFullyQualifiedName();
      }
      else  // valid location
        guardianLocation_ =
          locName.getGuardianFullyQualifiedName();
      break;

    case ElemDDLLocation::LOCATION_OSS_NAME :
      locName.copy(getLocationName(),
                   ComLocationName::OSS_LOCATION_NAME_FORMAT);
      if (NOT locName.isValid())
      {
        // Illegal location name format.
        *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName());
        guardianLocation_ =
          defaultLocName.getGuardianFullyQualifiedName();
      }
      else  // valid location
        guardianLocation_ =
          locName.getGuardianFullyQualifiedName();
      break;

#if 0
      //
      // Currently we do not handle this case
      // The grammar productions don't accept this syntax.
      // So comment out the following code for now.
      //
    case ElemDDLLocation::LOCATION_ENVIRONMENT_VARIABLE :
      {
        NAString envVarName(getLocationName());
        //
        // if the specified OSS environment variable has the
        // dollar sign prefix, removes it.
        //
	    if (envVarName[(size_t) 0] EQU '$')            // NT_PORT FIX SK 07/15/96
        {
          envVarName = envVarName(1/*startpos*/, envVarName.length() - 1);
        }
        const char * pEnvVarValue = getenv((const char *)envVarName);
        NAString locationName;
        if (pEnvVarValue NEQ NULL)
        {
          locationName = pEnvVarValue;
        }
        if (locationName.isNull())
        {
          guardianLocation_ = defaultLocName.
                              getGuardianFullyQualifiedName();
        }
        else
        {
          guardianLocationName = locationName;
          if (guardianLocationName.isValid())
          {
            guardianLocation_ = (guardianLocationName.
                                 getGuardianFullyQualifiedName());
            
          }
          else
          {
            ossLocationName = locationName;
            if (ossLocationName.isValid())
            {
              guardianLocation_ = (ossLocationName.
                                   getGuardianFullyQualifiedName());
            }
            else
            {
              // OSS environment variable $1~string1 contains illegal
              // location name $0~string0.
              *SqlParser_Diags << DgSqlCode(-3061) 
		<< DgString0(locationName)
	        << DgString1(envVarName)
		;
            }
          }
        }
      }
      break;
#endif // 0

    default :
      NAAbort("ElemDDLPartition.C", __LINE__, "internal logic error");
      break;
    }
  }

  markAsBound();
  return this;
}