Пример #1
0
void
MidiMixerWindow::slotFaderLevelChanged(float value)
{
    const QObject *s = sender();

    for (FaderVector::const_iterator it = m_faders.begin();
            it != m_faders.end(); ++it) {
        if ((*it)->m_volumeFader == s) {
            Instrument *instr = m_studio->
                                getInstrumentById((*it)->m_id);

            if (instr) {

                instr->setControllerValue(MIDI_CONTROLLER_VOLUME, MidiByte(value));

                if (instr->hasFixedChannel())
                {
                    // send out to external controllers as well if the
                    // affected instrument is on a fixed channel.
                    
                    //!!! really want some notification of whether we have any!
                    int tabIndex = m_tabWidget->currentIndex();
                    if (tabIndex < 0)
                        tabIndex = 0;
                    int i = 0;
                    for (DeviceList::const_iterator dit = m_studio->begin();
                         dit != m_studio->end(); ++dit) {
                        RG_DEBUG << "slotFaderLevelChanged: i = " << i << ", tabIndex " << tabIndex << endl;
                        if (!dynamic_cast<MidiDevice*>(*dit))
                            continue;
                        if (i != tabIndex) {
                            ++i;
                            continue;
                        }
                        RG_DEBUG << "slotFaderLevelChanged: device id = " << instr->getDevice()->getId() << ", visible device id " << (*dit)->getId() << endl;
                        if (instr->getDevice()->getId() == (*dit)->getId()) {
                            RG_DEBUG << "slotFaderLevelChanged: sending control device mapped event for channel " << instr->getNaturalChannel() << endl;

                            MappedEvent mE((*it)->m_id,
                                           MappedEvent::MidiController,
                                           MIDI_CONTROLLER_VOLUME,
                                           MidiByte(value));

                            mE.setRecordedChannel(instr->getNaturalChannel());
                            mE.setRecordedDevice(Device::CONTROL_DEVICE);
                            StudioControl::sendMappedEvent(mE);
                        }
                        break;
                    }
                }
            }

            emit instrumentParametersChanged((*it)->m_id);
            return ;
        }
    }
}
Пример #2
0
int main() {
  float f[] = {1, 2, 3, 4};
  FloatMatrixRef m(f, 2, 2);
  REF_TO_EIGEN(m, mE);

  assert(mE.rows() == 2);
  assert(mE.cols() == 2);
  assert(mE.sum() == 10);

  std::cout << mE << "\n";

  mE(0, 1) = 6;
  mE(1, 1) = 5;
  assert(f[0] == 1);
  assert(f[1] == 2);
  assert(f[2] == 6);  // default: use column major
  assert(f[3] == 5);

  return 0;
}
Пример #3
0
void
MidiMixerWindow::sendControllerRefresh()
{
    //!!! need to know if we have a current external controller device,
    // as this is expensive

    int tabIndex = m_tabWidget->currentIndex();
    RG_DEBUG << "MidiMixerWindow::slotCurrentTabChanged: current is " << tabIndex << endl;

    if (tabIndex < 0)
        return ;

    int i = 0;

    for (DeviceList::const_iterator dit = m_studio->begin();
            dit != m_studio->end(); ++dit) {

        MidiDevice *dev = dynamic_cast<MidiDevice*>(*dit);
        RG_DEBUG << "device is " << (*dit)->getId() << ", dev " << dev << endl;

        if (!dev)
            continue;
        if (i != tabIndex) {
            ++i;
            continue;
        }

        InstrumentList instruments = dev->getPresentationInstruments();
        ControlList controls = getIPBForMidiMixer(dev);

        RG_DEBUG << "device has " << instruments.size() << " presentation instruments, " << dev->getAllInstruments().size() << " instruments " << endl;

        for (InstrumentList::const_iterator iIt =
                    instruments.begin(); iIt != instruments.end(); ++iIt) {

            Instrument *instrument = *iIt;
            if (!instrument->hasFixedChannel()) { continue; }
            int channel = instrument->getNaturalChannel();

            RG_DEBUG << "instrument is " << instrument->getId() << endl;

            for (ControlList::const_iterator cIt =
                        controls.begin(); cIt != controls.end(); ++cIt) {

                int controller = (*cIt).getControllerValue();
                int value;
                try {
                    value = instrument->getControllerValue(controller);
                } catch (std::string s) {
                    std::cerr << "Exception in MidiMixerWindow::currentChanged: " << s << " (controller " << controller << ", instrument " << instrument->getId() << ")" << std::endl;
                    value = 0;
                }

                MappedEvent mE(instrument->getId(),
                               MappedEvent::MidiController,
                               controller, value);
                mE.setRecordedChannel(channel);
                mE.setRecordedDevice(Device::CONTROL_DEVICE);
                StudioControl::sendMappedEvent(mE);
            }

            MappedEvent mE(instrument->getId(),
                           MappedEvent::MidiController,
                           MIDI_CONTROLLER_VOLUME,
                           instrument->getVolume());
            mE.setRecordedChannel(channel);
            mE.setRecordedDevice(Device::CONTROL_DEVICE);
            RG_DEBUG << "sending controller mapped event for channel " << channel << ", volume " << instrument->getVolume() << endl;
            StudioControl::sendMappedEvent(mE);
        }

        break;
    }
}
Пример #4
0
void
MidiMixerWindow::slotControllerChanged(float value)
{
    const QObject *s = sender();
    size_t i = 0, j = 0;

    for (i = 0; i < m_faders.size(); ++i) {
        for (j = 0; j < m_faders[i]->m_controllerRotaries.size(); ++j) {
            if (m_faders[i]->m_controllerRotaries[j].second == s)
                break;
        }

        // break out on match
        if (j != m_faders[i]->m_controllerRotaries.size())
            break;
    }

    // Don't do anything if we've not matched and got solid values
    // for i and j
    //
    if (i == m_faders.size() || j == m_faders[i]->m_controllerRotaries.size())
        return ;

    //RG_DEBUG << "MidiMixerWindow::slotControllerChanged - found a controller"
    //<< endl;

    Instrument *instr = m_studio->getInstrumentById(
                            m_faders[i]->m_id);

    if (instr) {

        //RG_DEBUG << "MidiMixerWindow::slotControllerChanged - "
        //<< "got instrument to change" << endl;

        instr->setControllerValue(m_faders[i]->
                                  m_controllerRotaries[j].first,
                                  MidiByte(value));

        if (instr->hasFixedChannel()) {
            int tabIndex = m_tabWidget->currentIndex();
            if (tabIndex < 0)
                tabIndex = 0;
            int k = 0;
            for (DeviceList::const_iterator dit = m_studio->begin();
                 dit != m_studio->end(); ++dit) {
                RG_DEBUG << "slotControllerChanged: k = " << k << ", tabIndex " << tabIndex << endl;
                if (!dynamic_cast<MidiDevice*>(*dit))
                    continue;
                if (k != tabIndex) {
                    ++k;
                    continue;
                }
                RG_DEBUG << "slotControllerChanged: device id = " << instr->getDevice()->getId() << ", visible device id " << (*dit)->getId() << endl;
                if (instr->getDevice()->getId() == (*dit)->getId()) {
                    RG_DEBUG << "slotControllerChanged: sending control device mapped event for channel " << instr->getNaturalChannel() << endl;
                    // send out to external controllers as well.
                    //!!! really want some notification of whether we have any!
                    MappedEvent mE(m_faders[i]->m_id,
                                   MappedEvent::MidiController,
                                   m_faders[i]->m_controllerRotaries[j].first,
                                   MidiByte(value));
                    mE.setRecordedChannel(instr->getNaturalChannel());
                    mE.setRecordedDevice(Device::CONTROL_DEVICE);
                    StudioControl::sendMappedEvent(mE);
                }
            }
        }
        emit instrumentParametersChanged(m_faders[i]->m_id);
    }
}
Пример #5
0
void cGenSysSurResol::GSSR_AddContrainteIndexee
     (
         const std::vector<int> & aVI,
         REAL * aC,
         REAL aE
      )
{
    AssertPhaseContrainte();
 
 // Gestion specifique des contraintes univariees
   if ((! mNewCstrIsInit) && mUseSpeciCstrUniVar)
   {
       mIsCstr = Im1D_U_INT1(NbVar(),0);
       mDIsCstr = mIsCstr.data();
       mValCstr = Im1D_REAL8(NbVar(),0.0);
       mDValCstr = mValCstr.data();
       mNewCstrIsInit = true;
   }
   else
   {
       ELISE_ASSERT(mValCstr.tx()==NbVar(),"Sz - Incoherence in GSSR_AddContrainte");
   }
   int aNbVarNN = 0;
   int aKNN = -1;
   for (int y=0 ; y<int(aVI.size()) ; y++)
   {
       if (aC[y] !=0)
       {
            aNbVarNN++;
            aKNN = y;
       } 
   }


   if ((aNbVarNN==1) && mUseSpeciCstrUniVar)
   {
        mDIsCstr[aVI[aKNN]] = 1;
        mValCstr.data()[aVI[aKNN]] = aE/aC[aKNN];
       // std::cout << "xrt-CSTR[" << aVI[aKNN] <<"] = "  << aE/aC[aKNN]   << " C=" << aC[aKNN] << "\n";
        return;
   }
           

 // Gestion des contrainte l'ancienne si pas univariee

    mNbContrainte++;
    // Premiere contrainte
    if (mNbContrainte == 1)
    {
       ELISE_ASSERT(AcceptContrainteNonUniV(),"Ce systeme n'accepte que les contraintes uni var");
       mC.set_to_size(NbVar(),NbVar());
       mE.set_to_size(1,NbVar());
       // a priori inutile, mais pour initialiser toujours
       for (int y=0 ; y<NbVar() ; y++)
           mE(0,y) = 0;
       mtL.set_to_size(NbVar(),1);
       mtLC.set_to_size(NbVar(),1);
       mSol.set_to_size(1,NbVar());
       mCSol.set_to_size(1,NbVar());
    }
    mLineCC = NbVar() -mNbContrainte;
    ELISE_ASSERT(mLineCC>=0,"Too much contrainte in cGenSysSurResol");

    for (INT aV=0; aV<NbVar(); aV++)
    {
        mC(aV,mLineCC) = 0;
    }
    for (int y=0 ; y<int(aVI.size()) ; y++)
    {
        mC(aVI[y],mLineCC) = aC[y];
    }
    mE(0,mLineCC) = aE;
}
Пример #6
0
Im1D_REAL8  L2SysSurResol::Solve(bool * aResOk)
{
   if (mOptSym)
   {
      ELISE_ASSERT(mNbContrainte==0,"L2SysSurResol::Solve");
      for (int aK1=0 ; aK1 <mNbVar ; aK1++)
      {
          for (int aK2=0 ; aK2 <aK1 ; aK2++)
              mDatatLi_Li[aK1][aK2] =   mDatatLi_Li[aK2][aK1];
      }
   }
// std::cout << "L2SysSurResol " << mDatatLi_Li[0][1] << " " << mDatatLi_Li[1][0]  << "\n";
// getchar();

   if (mNbContrainte)
   {

	INT NbVarTot = mNbVar + mNbContrainte;
        GaussjPrec aGP(NbVarTot,1);
        ElMatrix<REAL> & M  = aGP.M();
        ElMatrix<REAL> & b  = aGP.b();
        ElMatrix<REAL> & x  = aGP.x();

        for (INT ky=0;ky <NbVarTot ; ky++)
        {
	   if (ky < mNbVar)
               b(0,ky) = mbi_Li.data()[ky];
	   else 
	       b(0,ky) = mE(0,mLineCC+ky-mNbVar);


           for (INT kx=0;kx <NbVarTot ; kx++)
           {
	       if ((kx<mNbVar) && (ky<mNbVar))
	       {
                   M(kx,ky) = mtLi_Li.data()[kx][ky];
	       }
	       else if ((kx>=mNbVar) && (ky>=mNbVar))
	       {
                   M(kx,ky) = 0;
	       }
	       else 
	       {
		   INT X = std::min(kx,ky);   
		   INT Y = std::max(kx,ky);   
		   M(kx,ky) =  mC(X,mLineCC+Y-mNbVar);
	       }
           }
        }
        bool Ok = aGP.init_rec();
	if ( aResOk)
           *aResOk = Ok;

	if (Ok)
	{
            for (INT k=0; k<6; k++)
	        aGP.amelior_sol();
            for (INT kx=0;kx <mNbVar ; kx++)
	        mSolL2.data()[kx] = x(0,kx);
	}
        else
        {
           ELISE_ASSERT(aResOk,"Singular Matrix in  L2SysSurResol::Solve");
        }

        return mSolL2;
   }
    GaussjPrec aGP(mNbVar,1);
    ElMatrix<REAL> & M  = aGP.M();
    ElMatrix<REAL> & b  = aGP.b();
    ElMatrix<REAL> & x  = aGP.x();


    for (INT ky=0;ky <mNbVar ; ky++)
    {
           b(0,ky) = mbi_Li.data()[ky];
           for (INT kx=0;kx <mNbVar ; kx++)
           {
               M(kx,ky) = mtLi_Li.data()[kx][ky];
           }
    }



    bool Ok = aGP.init_rec();

    if (aResOk)
       *aResOk = Ok;
/*
    cout << "L2SysSurResol::Solve GP " << Ok << "\n";
    if (! Ok)
    {
         for (INT ky=0;ky <mNbVar ; ky++)
         {
             for (INT kx=0;kx <mNbVar ; kx++)
             {
                 cout <<  mtLi_Li.data()[kx][ky] << " ";
             }
             cout << "\n";
         }
         cout << "----------------\n";
    }
*/
    if (Ok)
    {
        for (INT k=0; k<6; k++)
	    aGP.amelior_sol();

         for (INT kx=0;kx <mNbVar ; kx++)
	     mSolL2.data()[kx] = x(0,kx);
    }
     return mSolL2;
}
Пример #7
0
antlr::RefToken FMTLexer::nextToken()
{
	antlr::RefToken theRetToken;
	for (;;) {
		antlr::RefToken theRetToken;
		int _ttype = antlr::Token::INVALID_TYPE;
		resetText();
		try {   // for lexical and char stream error handling
			switch ( LA(1)) {
			case 0x22 /* '\"' */ :
			case 0x27 /* '\'' */ :
			{
				mSTRING(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x28 /* '(' */ :
			{
				mLBRACE(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x29 /* ')' */ :
			{
				mRBRACE(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x2f /* '/' */ :
			{
				mSLASH(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x2c /* ',' */ :
			{
				mCOMMA(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x41 /* 'A' */ :
			case 0x61 /* 'a' */ :
			{
				mA(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x3a /* ':' */ :
			{
				mTERM(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x24 /* '$' */ :
			{
				mNONL(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x46 /* 'F' */ :
			case 0x66 /* 'f' */ :
			{
				mF(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x44 /* 'D' */ :
			case 0x64 /* 'd' */ :
			{
				mD(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x45 /* 'E' */ :
			case 0x65 /* 'e' */ :
			{
				mE(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x47 /* 'G' */ :
			case 0x67 /* 'g' */ :
			{
				mG(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x49 /* 'I' */ :
			case 0x69 /* 'i' */ :
			{
				mI(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x4f /* 'O' */ :
			case 0x6f /* 'o' */ :
			{
				mO(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x42 /* 'B' */ :
			case 0x62 /* 'b' */ :
			{
				mB(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x5a /* 'Z' */ :
			{
				mZ(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x7a /* 'z' */ :
			{
				mZZ(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x51 /* 'Q' */ :
			case 0x71 /* 'q' */ :
			{
				mQ(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x48 /* 'H' */ :
			case 0x68 /* 'h' */ :
			{
				mH(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x54 /* 'T' */ :
			case 0x74 /* 't' */ :
			{
				mT(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x4c /* 'L' */ :
			case 0x6c /* 'l' */ :
			{
				mL(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x52 /* 'R' */ :
			case 0x72 /* 'r' */ :
			{
				mR(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x58 /* 'X' */ :
			case 0x78 /* 'x' */ :
			{
				mX(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x2e /* '.' */ :
			{
				mDOT(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x9 /* '\t' */ :
			case 0x20 /* ' ' */ :
			{
				mWHITESPACE(true);
				theRetToken=_returnToken;
				break;
			}
			case 0x2b /* '+' */ :
			case 0x2d /* '-' */ :
			case 0x30 /* '0' */ :
			case 0x31 /* '1' */ :
			case 0x32 /* '2' */ :
			case 0x33 /* '3' */ :
			case 0x34 /* '4' */ :
			case 0x35 /* '5' */ :
			case 0x36 /* '6' */ :
			case 0x37 /* '7' */ :
			case 0x38 /* '8' */ :
			case 0x39 /* '9' */ :
			{
				mNUMBER(true);
				theRetToken=_returnToken;
				break;
			}
			default:
				if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x4f /* 'O' */ ) && (LA(4) == 0x41 /* 'A' */ )) {
					mCMOA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x4f /* 'O' */ ) && (LA(4) == 0x49 /* 'I' */ )) {
					mCMOI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x6f /* 'o' */ )) {
					mCMoA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x49 /* 'I' */ )) {
					mCDI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x4d /* 'M' */ ) && (LA(3) == 0x49 /* 'I' */ )) {
					mCMI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x53 /* 'S' */ ) && (LA(3) == 0x49 /* 'I' */ )) {
					mCSI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x53 /* 'S' */ ) && (LA(3) == 0x46 /* 'F' */ )) {
					mCSF(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x57 /* 'W' */ )) {
					mCDWA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x44 /* 'D' */ ) && (LA(3) == 0x77 /* 'w' */ )) {
					mCDwA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x41 /* 'A' */ ) && (LA(3) == 0x50 /* 'P' */ )) {
					mCAPA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x41 /* 'A' */ ) && (LA(3) == 0x70 /* 'p' */ )) {
					mCApA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x25 /* '%' */ ) && (LA(2) == 0x22 /* '\"' */  || LA(2) == 0x27 /* '\'' */ )) {
					mCSTRING(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x6d /* 'm' */ )) {
					mCmoA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x59 /* 'Y' */ )) {
					mCYI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x48 /* 'H' */ )) {
					mCHI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x68 /* 'h' */ )) {
					mChI(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x64 /* 'd' */ )) {
					mCdwA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */ ) && (LA(2) == 0x61 /* 'a' */ )) {
					mCapA(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x43 /* 'C' */  || LA(1) == 0x63 /* 'c' */ ) && (true)) {
					mC(true);
					theRetToken=_returnToken;
				}
				else if ((LA(1) == 0x25 /* '%' */ ) && (true)) {
					mPERCENT(true);
					theRetToken=_returnToken;
				}
			else {
				if (LA(1)==EOF_CHAR)
				{
					uponEOF();
					_returnToken = makeToken(antlr::Token::EOF_TYPE);
				}
				else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());}
			}
			}
			if ( !_returnToken )
				goto tryAgain; // found SKIP token

			_ttype = _returnToken->getType();
			_ttype = testLiteralsTable(_ttype);
			_returnToken->setType(_ttype);
			return _returnToken;
		}
		catch (antlr::RecognitionException& e) {
				throw antlr::TokenStreamRecognitionException(e);
		}
		catch (antlr::CharStreamIOException& csie) {
			throw antlr::TokenStreamIOException(csie.io);
		}
		catch (antlr::CharStreamException& cse) {
			throw antlr::TokenStreamException(cse.getMessage());
		}
tryAgain:;
	}
}
Пример #8
0
bool poly::giftwrap(){
	
	if (surface.size() != 0) 
		surface.clear();
	
		// sort by x coordinate
	sortPoints(0);
		// first points is minimum x
	point p1 = points[0]; point* p1_ptr = &points[0];
	
		// 2nd point is found by 2d giftwrap in xy plane
	double maxDot = -1.;
	point p2; point* p2_ptr;
	for (int i=1;i<points.size();i++){
		point delta = points[i] - p1;
		delta.setX(2,0.);
		delta.makeUnit();
		double dDot = delta * point(0,1,0);
		
		std::cout << delta << " * " << points[i] << " : " << dDot << std::endl;
		if (maxDot < dDot){
			maxDot = dDot;
			p2 = points[i];
			p2_ptr = &points[i];
		}
		else if (dDot == maxDot)
			if ( (points[i] - p1).mag() < p2.mag()){
				maxDot = dDot;
				p2 = points[i];
				p2_ptr = &points[i];
			}
	}
	
	std::cout << p1 << "   " << p2 << std::endl;
	
		// project into plane defined by edge
		// between the first two points
	point dp = p2 - p1;
	dp.makeUnit();
		// origin in projected space
	point p0 = p1 - dp * (dp*p1);
	
	std::vector<point> pp;
	for (int i=1;i<points.size();i++)
		if (points[i] != p2)
			pp.push_back(points[i] - dp * (dp*points[i]) - p0);
	
		// find all possible pairs of points
	std::vector<point> ppairs1;
	std::vector<point> ppairs2;
	for (int i=0;i<pp.size();i++)
		for (int j=i+1;j<pp.size();j++){
			ppairs1.push_back(pp[i]);
			ppairs2.push_back(pp[j]);
		}
	
	pp.clear();

		// find the two points in this space 
		// with the largest opening angle
	point pp1, pp2;
	double minDot = 2.;
	for (int i=0;i<ppairs1.size();i++){
		double dDot = (ppairs1[i]*ppairs2[i])/(ppairs1[i].mag()*ppairs2[i].mag());
		if (dDot < minDot){
			minDot = dDot;
			pp1 = ppairs1[i];
			pp2 = ppairs2[i];
		}
		else if (dDot == minDot)
			if ( (ppairs1[i]-ppairs2[i]).mag() < (pp1-pp2).mag()){
				minDot = dDot;
				pp1 = ppairs1[i];
				pp2 = ppairs2[i];
			}
	}
	
	ppairs1.clear();
	ppairs2.clear();
	
		// find the poitns in original space
		// that match the points at large angles
		// these are the first two triangles
	for (int i=0;i<points.size();i++){
		point mPP = points[i] - dp*(dp*points[i]) - p0;
		if (mPP==pp1 || mPP==pp2)
			surface.push_back(tri(*p1_ptr,*p2_ptr,points[i]));
	}
	
	if (!markEdges())
		return false;
	
		//	for (int j=0;j<surface.size();j++)
		//		std::cout << "surface["<<j<< "] : " << surface[j] << std::endl;
		//	std::cout << std::endl;
	
	while (isSurfaceOpen()){
		edge mE;
		point mP;
		
		for (int i=0;i<surface.size();i++){
			
			if (!surface[i].getUnconnected(mE, mP))
				continue;
			
			dp = mE(1) - mE(0);
			dp.makeUnit();
			p0 = mE(1) - dp*(dp*mE(1));
			point mPP = mP - dp*(dp*mP) - p0;
			mPP = -mPP/(mPP.mag());
			
			std::vector<point> ppoints;
			for (int j=0;j<points.size();j++){
				if (surface[i].hasPoint(points[j]))
					continue;
				ppoints.push_back(points[j] - dp *(dp*points[j]) - p0);
			}
			
			double maxDot = -2.;
			point nPP;
				// find most colinear
			for (int j=0;j<ppoints.size();j++){
				double dDot = (ppoints[j]*mPP)/ppoints[j].mag();
				if (dDot > maxDot){
					maxDot = dDot;
					nPP = ppoints[j];
				}
					// if there are planar points, take the closest one
				else if (dDot == maxDot)
					if ( ppoints[j].mag() < nPP.mag()){
						maxDot = dDot;
						nPP = ppoints[j];
					}
			}
			ppoints.clear();

			for (int j=0;j<points.size();j++)
				if (nPP == points[j] - dp*(dp*points[j]) - p0)
					surface.push_back(tri(mE(0),mE(1),points[j]));

				//			for (int j=0;j<surface.size();j++)
				//				std::cout << "surface["<<j<< "] : " << surface[j] << std::endl;
				//			std::cout << std::endl;
			
			if (!markEdges()) {
				return false;
				
					//unmarkEdges();
					//surface.pop_back();
				
					//for (int j=0;j<surface.size();j++)
					//std::cout << "surface["<<j<< "] : " << surface[j] << std::endl;
					//std::cout << std::endl;
					//continue;
			}
			break;
				
		}
	}
	
	calcCenter();
	fixN();
	
	return true;
}