← Back to team overview

yade-dev team mailing list archive

[svn] r1641 - in trunk: core examples examples/SpheresFactory gui/py lib/import pkg/common pkg/common/Engine/MetaEngine pkg/common/Engine/StandAloneEngine

 

Author: sega
Date: 2009-01-25 15:28:37 +0100 (Sun, 25 Jan 2009)
New Revision: 1641

Added:
   trunk/core/BroadInteractor.cpp
   trunk/examples/SpheresFactory/
   trunk/examples/SpheresFactory/circle.stl
   trunk/examples/SpheresFactory/model.py
   trunk/examples/SpheresFactory/plane.stl
   trunk/examples/SpheresFactory/square.stl
   trunk/examples/SpheresFactory/yade.stl
Modified:
   trunk/core/BroadInteractor.hpp
   trunk/core/SConscript
   trunk/examples/STLImporterTest.py
   trunk/gui/py/utils.py
   trunk/gui/py/yadeControl.cpp
   trunk/lib/import/STLImporter.cpp
   trunk/lib/import/STLImporter.hpp
   trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
   trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.hpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp
   trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp
   trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.cpp
   trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.hpp
   trunk/pkg/common/SConscript
Log:
1.First worked version of SpheresFactory engine. Example in examples/SpheresFactory
2.Added PersistentSAPCollider::probeBoundingVolume function (for using with SpheresFactory)
3.InteractionGeometryMetaEngine::explicitAction has been modified to remove artifical (as me seems) asserts.
4.python import_stl_geometry now return list of body ids instead only their number.
5.import stl geometry now allows import facets without BoundingVolume  and InteractingGeometry.
6.Fixed dynamic_cast for BroadInteractor. 



Added: trunk/core/BroadInteractor.cpp
===================================================================
--- trunk/core/BroadInteractor.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/core/BroadInteractor.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -0,0 +1,20 @@
+/*************************************************************************
+*  Copyright (C) 2004 by Janek Kozicki                                   *
+*  cosurgi@xxxxxxxxxx                                                    *
+*                                                                        *
+*  This program is free software; it is licensed under the terms of the  *
+*  GNU General Public License v2 or later. See file LICENSE for details. *
+*************************************************************************/
+
+#include "BroadInteractor.hpp"
+
+BroadInteractor::BroadInteractor()
+{
+	
+}
+
+BroadInteractor::~BroadInteractor()
+{
+	
+}
+

Modified: trunk/core/BroadInteractor.hpp
===================================================================
--- trunk/core/BroadInteractor.hpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/core/BroadInteractor.hpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -15,9 +15,9 @@
 class BroadInteractor : public StandAloneEngine
 {
 	public :
-		BroadInteractor() {};
-		virtual ~BroadInteractor() {};
-		virtual  bool probeBoundingVolume(const shared_ptr<BoundingVolume>& bv, const Vector3r& center){throw;}
+		BroadInteractor();
+		virtual ~BroadInteractor();
+		virtual  bool probeBoundingVolume(const BoundingVolume&){throw;}
 		vector<body_id_t> probedBodies;
 
 	protected:

Modified: trunk/core/SConscript
===================================================================
--- trunk/core/SConscript	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/core/SConscript	2009-01-25 14:28:37 UTC (rev 1641)
@@ -4,6 +4,7 @@
 		['Body.cpp',
 			'BodyContainer.cpp',
 			'BoundingVolume.cpp',
+			'BroadInteractor.cpp',
 			'DeusExMachina.cpp',
 			'FileGenerator.cpp',
 			'FrontEnd.cpp',

Modified: trunk/examples/STLImporterTest.py
===================================================================
--- trunk/examples/STLImporterTest.py	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/examples/STLImporterTest.py	2009-01-25 14:28:37 UTC (rev 1641)
@@ -74,7 +74,7 @@
 	## Angular acceleration changes angular velocity, resulting in position and/or orientation change of the body.
 	MetaEngine('PhysicalParametersMetaEngine',[EngineUnit('LeapFrogOrientationIntegrator')]),
 	## Apply kinematics to walls
-	DeusExMachina('RotationEngine',{'subscribedBodies':range(imported),'rotationAxis':[0,0,1],'rotateAroundZero':True,'angularVelocity':0.5}),
+	DeusExMachina('RotationEngine',{'subscribedBodies':imported,'rotationAxis':[0,0,1],'rotateAroundZero':True,'angularVelocity':0.5}),
 ]
 
 ## Save the scene to file, so that it can be loaded later. Supported extension are: .xml, .xml.gz, .xml.bz2.

Added: trunk/examples/SpheresFactory/circle.stl
===================================================================
(Binary files differ)


Property changes on: trunk/examples/SpheresFactory/circle.stl
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/SpheresFactory/model.py
===================================================================
--- trunk/examples/SpheresFactory/model.py	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/examples/SpheresFactory/model.py	2009-01-25 14:28:37 UTC (rev 1641)
@@ -0,0 +1,73 @@
+# -*- encoding=utf-8 -*-
+
+from yade import utils
+
+## Omega
+o=Omega() 
+
+## PhysicalParameters 
+Young = 0.15e9
+Poisson = 0.3
+
+## Import box geometry
+box = utils.import_stl_geometry('plane.stl',young=Young,poisson=Poisson,color=[0.7,0.7,0.7],wire=False)
+## Import factory geometry
+factory1 = utils.import_stl_geometry('yade.stl',color=[0.7,0.4,0.4],noInteractingGeometry=True)
+factory2 = utils.import_stl_geometry('circle.stl',color=[0.4,0.7,0.4],noInteractingGeometry=True)
+factory3 = utils.import_stl_geometry('square.stl',color=[0.4,0.4,0.7],noInteractingGeometry=True)
+
+## Timestep 
+o.dt=0.0001
+
+## Initializers 
+o.initializers=[
+	StandAloneEngine('PhysicalActionContainerInitializer'),
+	MetaEngine('BoundingVolumeMetaEngine',
+		[EngineUnit('InteractingSphere2AABB'),
+			EngineUnit('InteractingFacet2AABB'),
+			EngineUnit('MetaInteractingGeometry2AABB')])
+	]
+
+## Engines 
+o.engines=[
+	StandAloneEngine('PhysicalActionContainerReseter'),
+	MetaEngine('BoundingVolumeMetaEngine',[
+		EngineUnit('InteractingSphere2AABB'),
+		EngineUnit('InteractingFacet2AABB'),
+		EngineUnit('MetaInteractingGeometry2AABB')
+	]),
+	StandAloneEngine('PersistentSAPCollider'),
+
+	## Spheres factory engine
+	StandAloneEngine('SpheresFactory',{'factoryFacets':factory1,'virtPeriod':0.005,'radius':0.07,'radiusRange':0.03,'young':Young,'color':[1,0,0]}),
+	StandAloneEngine('SpheresFactory',{'factoryFacets':factory2,'virtPeriod':0.01,'radius':0.08,'young':Young,'color':[0,1,0]}),
+	StandAloneEngine('SpheresFactory',{'factoryFacets':factory3,'virtPeriod':0.01,'radius':0.05,'young':Young,'color':[0,0,1]}),
+
+	MetaEngine('InteractionGeometryMetaEngine',[
+		EngineUnit('InteractingSphere2InteractingSphere4SpheresContactGeometry'),
+		EngineUnit('InteractingFacet2InteractingSphere4SpheresContactGeometry')
+	]),
+	MetaEngine('InteractionPhysicsMetaEngine',[EngineUnit('MacroMicroElasticRelationships')]),
+
+	DeusExMachina('GravityEngine',{'gravity':[0,0,-9.81]}),
+	
+	StandAloneEngine('ElasticContactLaw'),
+	
+	MetaEngine('PhysicalActionDamper',[
+		EngineUnit('CundallNonViscousForceDamping',{'damping':0.3}),
+		EngineUnit('CundallNonViscousMomentumDamping',{'damping':0.3})
+	]),
+
+	MetaEngine('PhysicalActionApplier',[
+		EngineUnit('NewtonsForceLaw'),
+		EngineUnit('NewtonsMomentumLaw'),
+	]),
+
+	MetaEngine('PhysicalParametersMetaEngine',[EngineUnit('LeapFrogPositionIntegrator')]),
+	MetaEngine('PhysicalParametersMetaEngine',[EngineUnit('LeapFrogOrientationIntegrator')]),
+
+]
+
+## Save the scene to file, so that it can be loaded later. Supported extension are: .xml, .xml.gz, .xml.bz2.
+o.save('/tmp/a.xml');
+

Added: trunk/examples/SpheresFactory/plane.stl
===================================================================
(Binary files differ)


Property changes on: trunk/examples/SpheresFactory/plane.stl
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/SpheresFactory/square.stl
===================================================================
(Binary files differ)


Property changes on: trunk/examples/SpheresFactory/square.stl
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/SpheresFactory/yade.stl
===================================================================
(Binary files differ)


Property changes on: trunk/examples/SpheresFactory/yade.stl
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/gui/py/utils.py
===================================================================
--- trunk/gui/py/utils.py	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/gui/py/utils.py	2009-01-25 14:28:37 UTC (rev 1641)
@@ -225,22 +225,28 @@
 	pylab.show()
 
 
-def import_stl_geometry(file, begin=0, young=30e9,poisson=.3,frictionAngle=0.5236,wire=True):
-		## Import walls geometry from STL file
-		imp = STLImporter()
-		imp.wire = wire
-		imp.open(file)
-		o=Omega()
-		for i in xrange(imp.number_of_facets):
-			b=Body()
-			b['isDynamic']=False
-			b.phys=PhysicalParameters('BodyMacroParameters',{'se3':[0,0,0,1,0,0,0],'mass':0,'inertia':[0,0,0],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
+def import_stl_geometry(file, young=30e9,poisson=.3,color=[0,1,0],frictionAngle=0.5236,wire=True,noBoundingVolume=False,noInteractingGeometry=False):
+	""" Import geometry from stl file, create bodies and return list of their ids. 
+	"""
+	imp = STLImporter()
+	imp.wire = wire
+	imp.open(file)
+	o=Omega()
+	begin=len(o.bodies)
+	for i in xrange(imp.number_of_facets):
+		b=Body()
+		b['isDynamic']=False
+		b.phys=PhysicalParameters('BodyMacroParameters',{'se3':[0,0,0,1,0,0,0],'mass':0,'inertia':[0,0,0],'young':young,'poisson':poisson,'frictionAngle':frictionAngle})
+		if not noBoundingVolume:
 			b.bound=BoundingVolume('AABB',{'diffuseColor':[0,1,0]})
-			o.bodies.append(b)
-		imp.import_geometry(o.bodies,begin)
-		for i in xrange(begin,begin+imp.number_of_facets):
+		o.bodies.append(b)
+	imp.import_geometry(o.bodies,begin,noInteractingGeometry)
+	imported=range(begin,begin+imp.number_of_facets)
+	for i in imported:
+		if not noInteractingGeometry:
 			o.bodies[i].mold.postProcessAttributes()
-		return imp.number_of_facets
+		o.bodies[i].shape['diffuseColor']=color
+	return imported
 
 def encodeVideoFromFrames(wildcard,out,renameNotOverwrite=True,fps=24):
 	import pygst,sys,gobject,os

Modified: trunk/gui/py/yadeControl.cpp
===================================================================
--- trunk/gui/py/yadeControl.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/gui/py/yadeControl.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -532,10 +532,10 @@
 
 class pySTLImporter : public STLImporter {
     public:
-	void py_import(pyBodyContainer bc, unsigned int begin=0) { import(bc.proxee,begin); }
+	void py_import(pyBodyContainer bc, unsigned int begin=0, bool noInteractingGeometry=false) { import(bc.proxee,begin,noInteractingGeometry); }
 };
 
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(STLImporter_import_overloads,py_import,1,2);
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(STLImporter_import_overloads,py_import,1,3);
 
 BOOST_PYTHON_MODULE(wrapper)
 {

Modified: trunk/lib/import/STLImporter.cpp
===================================================================
--- trunk/lib/import/STLImporter.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/lib/import/STLImporter.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -35,7 +35,7 @@
 	return true;
 }
 
-void STLImporter::import(shared_ptr<BodyContainer> bodies, unsigned int begin)
+void STLImporter::import(shared_ptr<BodyContainer> bodies, unsigned int begin, bool noInteractingGeometry)
 {
 	unsigned int b_id = begin;
 	for(int i=0,e=tr.size(); i<e; i+=3)
@@ -61,7 +61,7 @@
 
 		(*bodies)[b_id]->physicalParameters->se3 = Se3r( icc, Quaternionr( 1,0,0,0 ) );
 		(*bodies)[b_id]->geometricalModel	= gFacet;
-		(*bodies)[b_id]->interactingGeometry	= iFacet;
+		if (!noInteractingGeometry) (*bodies)[b_id]->interactingGeometry	= iFacet;
 
 		++b_id;
 	}

Modified: trunk/lib/import/STLImporter.hpp
===================================================================
--- trunk/lib/import/STLImporter.hpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/lib/import/STLImporter.hpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -27,7 +27,7 @@
 	bool wire;
 
 	/// import geometry 
-	void import(shared_ptr<BodyContainer> bodies, unsigned int begin=0);
+	void import(shared_ptr<BodyContainer> bodies, unsigned int begin=0, bool noInteractingGeometry=false);
 
 	DECLARE_LOGGER;
 protected:

Modified: trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -20,13 +20,24 @@
  * The EngineUnit must not fail (return false).
  */
 
-shared_ptr<Interaction> InteractionGeometryMetaEngine::explicitAction(const shared_ptr<Body>& b1, const shared_ptr<Body> b2){
-	assert(b1->interactingGeometry && b2->interactingGeometry);
-	shared_ptr<Interaction> i(new Interaction(b1->getId(),b2->getId()));
-	i->isReal=true;
-	bool op=operator()(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3,b2->physicalParameters->se3,i);
-	if(!op) throw runtime_error("InteractionGeometryMetaEngine::explicitAction could not dispatch for given types ("+b1->interactingGeometry->getClassName()+","+b2->interactingGeometry->getClassName()+") or the dispatchee returned false.");
-	return i;
+shared_ptr<Interaction> InteractionGeometryMetaEngine::explicitAction(const shared_ptr<Body>& b1, const shared_ptr<Body>& b2){
+	//assert(b1->interactingGeometry && b2->interactingGeometry);
+	//shared_ptr<Interaction> i(new Interaction(b1->getId(),b2->getId()));
+	//i->isReal=true;
+	//bool op=operator()(b1->interactingGeometry,b2->interactingGeometry,b1->physicalParameters->se3,b2->physicalParameters->se3,i);
+	//if(!op) throw runtime_error("InteractionGeometryMetaEngine::explicitAction could not dispatch for given types ("+b1->interactingGeometry->getClassName()+","+b2->interactingGeometry->getClassName()+") or the dispatchee returned false.");
+	//return i;
+	
+	// Seems asserts and throws in code above is not good idea.
+	// Below code do same (i.e. create interaction for specified bodies), but
+	// without artifical exceptions. If creating interaction is fail (for
+	// example if bodies don't have an interactionGeometry), returned
+	// interaction is non real, i.e. interaction->isReal==false. Sega.
+	shared_ptr<Interaction> interaction(new Interaction(b1->getId(),b2->getId()));
+	interaction->isReal =
+		b1->interactingGeometry && b2->interactingGeometry && 
+		operator()( b1->interactingGeometry , b2->interactingGeometry , b1->physicalParameters->se3 , b2->physicalParameters->se3 , interaction );
+	return interaction;
 }
 
 void InteractionGeometryMetaEngine::action(MetaBody* ncb)
@@ -54,9 +65,9 @@
 		//cerr<<"isReal="<<interaction->isReal<<", wasReal="<<wasReal<<", isNew="<<interaction->isNew<<endl;
 
 		//tmp
-		if(!(b1->interactingGeometry&&b2->interactingGeometry)){
-			cerr<<__FILE__<<":"<<__LINE__<<": no interacting geometry "<< (b1->interactingGeometry?b1->getId():-1)<<" "<<(b2->interactingGeometry?b2->getId():-1)<<endl;
-		}
+		//if(!(b1->interactingGeometry&&b2->interactingGeometry)){
+			//cerr<<__FILE__<<":"<<__LINE__<<": no interacting geometry "<< (b1->interactingGeometry?b1->getId():-1)<<" "<<(b2->interactingGeometry?b2->getId():-1)<<endl;
+		//}
 			
 	}
 }

Modified: trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.hpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.hpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/MetaEngine/InteractionGeometryMetaEngine.hpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -37,7 +37,7 @@
 {
 	public :
 		virtual void action(MetaBody*);
-		shared_ptr<Interaction> explicitAction(const shared_ptr<Body>& b1, const shared_ptr<Body> b2);
+		shared_ptr<Interaction> explicitAction(const shared_ptr<Body>& b1, const shared_ptr<Body>& b2);
 
 	REGISTER_CLASS_NAME(InteractionGeometryMetaEngine);
 	REGISTER_BASE_CLASS_NAME(MetaEngine2D);

Modified: trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -104,7 +104,28 @@
 	}
 }
 
+bool PersistentSAPCollider::probeBoundingVolume(const BoundingVolume& bv)
+{
+	probedBodies.clear();
+	for( vector<shared_ptr<AABBBound> >::iterator 
+			it=xBounds.begin(),et=xBounds.end(); it < et; ++it)
+	{
+		if ((*it)->value > bv.max[0]) break;
+		if (!(*it)->lower) continue;
+		int offset = 3*(*it)->id;
+		if (!(maxima[offset] < bv.min[0] ||
+				minima[offset+1] > bv.max[1] ||
+				maxima[offset+1] < bv.min[1] ||
+				minima[offset+2] > bv.max[2] ||
+				maxima[offset+2] < bv.min[2] )) 
+		{
+			probedBodies.push_back((*it)->id);
+		}
+	}
+	return (bool)probedBodies.size();
+}
 
+
 void PersistentSAPCollider::updateIds(unsigned int nbElements)
 {
 	// the first time broadInteractionTest is called nbObject=0

Modified: trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/StandAloneEngine/PersistentSAPCollider.hpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -95,6 +95,9 @@
 		/// return a list "transientInteractions" of pairs of Body which Bounding volume are in potential interaction
 		void action(MetaBody *);
 
+		/// return true if BoundingVolume is in potential interaction
+		bool probeBoundingVolume(const BoundingVolume& bv);
+
 		//! When creating transient interaction, look first if a persistent link between the pair in question exists; in that case, skip it.
 		bool noTransientIfPersistentExists;
 		//! Don't break transient interaction once bodies don't overlap anymore; material law will be responsible for breaking it.

Modified: trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.cpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.cpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -8,19 +8,38 @@
 
 #include<boost/random.hpp>
 #include<yade/core/Body.hpp>
-#include<yade/pkg-common/PersistentSAPCollider.hpp>
 #include<yade/pkg-common/AABB.hpp>
 #include<yade/pkg-common/InteractingSphere.hpp>
-#include<yade/pkg-common/InteractingFacet.hpp>
+#include<yade/pkg-common/Facet.hpp>
 #include<yade/pkg-common/Sphere.hpp>
 #include<yade/pkg-dem/BodyMacroParameters.hpp>
 #include"SpheresFactory.hpp"
 
 CREATE_LOGGER(SpheresFactory);
 
-SpheresFactory::SpheresFactory() : first_run(true) 
+namespace {
+boost::variate_generator<boost::mt19937,boost::uniform_real<> > 
+	randomUnit(boost::mt19937(),boost::uniform_real<>(0,1));
+boost::variate_generator<boost::mt19937,boost::uniform_real<> >
+	randomSymmetricUnit(boost::mt19937(),boost::uniform_real<>(-1,1));
+}
+
+SpheresFactory::SpheresFactory() 
 {
-
+	factoryFacets.clear();
+	maxAttempts=20;
+	radius=0.01;
+	radiusRange=0;
+	velocity=Vector3r(0,0,0);
+	velocityRange=Vector3r(0,0,0);
+	angularVelocity=Vector3r(0,0,0);
+	angularVelocityRange=Vector3r(0,0,0);
+	young		= 0;
+	poisson		= 0;
+	frictionAngle = 0;
+	density 	= 2400;
+	first_run = true;
+	color=Vector3r(0.8,0.8,0.8);
 }
 
 SpheresFactory::~SpheresFactory()
@@ -28,46 +47,74 @@
 	
 }
 
-
-
 void SpheresFactory::action(MetaBody* ncb)
 {
 	if (first_run)
 	{
-		//FIXME: Why dynamic_cast failed here???
-		Engine* eng = ncb->engineByLabel(labelBroadInteractor).get();
-		bI=dynamic_cast<BroadInteractor*>(eng);
+		FOREACH(shared_ptr<Engine> eng, ncb->engines)
+		{
+			bI=dynamic_cast<BroadInteractor*>(eng.get());
+			if (bI) break;
+		}
 		if (!bI) 
 		{
-			LOG_FATAL("For engine with label '" << labelBroadInteractor << "' dynamic_cast from class '" << eng->getClassName() << "' to class 'BroadInteractor' failed!" );
+			LOG_FATAL("Can't find BroadInteractor." );
 			return;
 		}
+		iGME=dynamic_cast<InteractionGeometryMetaEngine*>(ncb->engineByName("InteractionGeometryMetaEngine").get());
+		if (!iGME) 
+		{
+			LOG_FATAL("Can't find InteractionGeometryMetaEngine." );
+			return;
+		}
 		first_run=false;
+		randomFacet= shared_ptr<RandomInt>(new RandomInt(boost::minstd_rand(),boost::uniform_int<>(0,factoryFacets.size()-1)));
 	}
 
-	static boost::variate_generator<boost::minstd_rand,boost::uniform_int<> > randomFacet(boost::minstd_rand(),boost::uniform_int<>(0,factoryFacets.size()-1));
 
-	static boost::variate_generator<boost::mt19937,boost::uniform_real<> > random(boost::mt19937(),boost::uniform_real<>(0,1));
 
-	body_id_t facetId = factoryFacets[randomFacet()];
-	Real t1 = random();
-	Real t2 = random()*(1-t1);
+	for (int attempt=0; attempt<maxAttempts; ++attempt)
+	{
+		body_id_t facetId = factoryFacets[(*randomFacet)()];
+		Real t1 = randomUnit();
+		Real t2 = randomUnit()*(1-t1);
 
-	shared_ptr<Body> facet = Body::byId(factoryFacets[facetId]);
-	InteractingFacet* ifacet = static_cast<InteractingFacet*>(facet->interactingGeometry.get());
+		shared_ptr<Body> facet = Body::byId(facetId);
+		Facet* gfacet = static_cast<Facet*>(facet->geometricalModel.get());
 
-	Vector3r position = t1*(ifacet->vertices[1]-ifacet->vertices[0])+t2*(ifacet->vertices[2]-ifacet->vertices[0])+ifacet->vertices[0]+facet->physicalParameters->se3.position;
+		Vector3r position = t1*(gfacet->vertices[1]-gfacet->vertices[0])+t2*(gfacet->vertices[2]-gfacet->vertices[0])+gfacet->vertices[0]+facet->physicalParameters->se3.position;
 
-	Real radius=0.1;
+		Real r=radius+radiusRange*randomSymmetricUnit();
 
-	shared_ptr<Body> sphere;
-	createSphere(sphere,position,radius);
-	ncb->bodies->insert(sphere);
+		BoundingVolume bv;
+		bv.min = Vector3r(position[0]-r, position[1]-r, position[2]-r);
+		bv.max = Vector3r(position[0]+r, position[1]+r, position[2]+r);
 
-	bI->action(ncb);
+		shared_ptr<Body> sphere;
+		createSphere(sphere,position,r);
+
+		if (bI->probeBoundingVolume(bv)) 
+		{
+			bool is_overlap=false;
+			for( unsigned int i=0, e=bI->probedBodies.size(); i<e; ++i)
+			{
+				if (iGME->explicitAction(sphere,Body::byId(bI->probedBodies[i]))->isReal)
+				{
+					is_overlap=true;
+					break;
+				}
+			}
+			if (is_overlap) continue;
+		}
+		ncb->bodies->insert(sphere);
+		bI->action(ncb);
+		return;
+	}
+	LOG_WARN("Can't placing sphere during " << maxAttempts << " attemps.");
 }
 
-void SpheresFactory::createSphere(shared_ptr<Body>& body, const Vector3r& position, Real radius)
+void SpheresFactory::createSphere(shared_ptr<Body>& body, 
+		const Vector3r& position, Real r)
 {
 	body = shared_ptr<Body>(new Body(body_id_t(0),1));
 	shared_ptr<BodyMacroParameters> physics(new BodyMacroParameters);
@@ -78,27 +125,36 @@
 	Quaternionr q;
 	q.FromAxisAngle( Vector3r(0,0,1),0);
 	
-	body->isDynamic			= false;
+	body->isDynamic			= true;
 	
-	physics->angularVelocity	= Vector3r(0,0,0);
-	physics->velocity		= Vector3r(0,0,0);
-	physics->mass			= 4.0/3.0*Mathr::PI*radius*radius*radius*2400;
-	physics->inertia		= Vector3r(2.0/5.0*physics->mass*radius*radius,2.0/5.0*physics->mass*radius*radius,2.0/5.0*physics->mass*radius*radius); //
+	physics->velocity		= Vector3r(//
+			velocity[0]+velocityRange[0]*randomSymmetricUnit(),
+			velocity[1]+velocityRange[1]*randomSymmetricUnit(),
+			velocity[2]+velocityRange[2]*randomSymmetricUnit());
+	physics->angularVelocity= Vector3r(//
+			angularVelocity[0]+angularVelocityRange[0]*randomSymmetricUnit(),
+			angularVelocity[1]+angularVelocityRange[1]*randomSymmetricUnit(),
+			angularVelocity[2]+angularVelocityRange[2]*randomSymmetricUnit());
+	physics->mass			= 4.0/3.0*Mathr::PI*r*r*r*density;
+	physics->inertia = Vector3r(//
+			2.0/5.0*physics->mass*r*r,
+			2.0/5.0*physics->mass*r*r,
+			2.0/5.0*physics->mass*r*r); 
 	physics->se3			= Se3r(position,q);
-	physics->young			= 0.15e9;
-	physics->poisson		= 0.3;
-	//physics->frictionAngle	= sphereFrictionDeg * Mathr::PI/180.0;
+	if (young) 			physics->young			= young;
+	if (poisson) 		physics->poisson		= poisson;
+	if (frictionAngle) 	physics->frictionAngle	= frictionAngle;
 
 	aabb->diffuseColor		= Vector3r(0,1,0);
 
-	gSphere->radius			= radius;
-	gSphere->diffuseColor		= Vector3r(Mathr::UnitRandom(),Mathr::UnitRandom(),Mathr::UnitRandom());
+	gSphere->radius			= r;
+	gSphere->diffuseColor	= color;
 	gSphere->wire			= false;
 	gSphere->visible		= true;
-	gSphere->shadowCaster		= true;
+	gSphere->shadowCaster	= true;
 	
-	iSphere->radius			= radius;
-	iSphere->diffuseColor		= Vector3r(0.8,0.3,0.3);
+	iSphere->radius			= r;
+	iSphere->diffuseColor	= Vector3r(0.8,0.3,0.3);
 
 	body->interactingGeometry	= iSphere;
 	body->geometricalModel		= gSphere;

Modified: trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.hpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.hpp	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/Engine/StandAloneEngine/SpheresFactory.hpp	2009-01-25 14:28:37 UTC (rev 1641)
@@ -8,7 +8,8 @@
 #ifndef ___SPHERESFACTORYENGINE___
 #define ___SPHERESFACTORYENGINE___
 
-#include <yade/core/StandAloneEngine.hpp>
+#include <yade/pkg-common/PeriodicEngines.hpp>
+#include <yade/pkg-common/InteractionGeometryMetaEngine.hpp>
 #include <yade/core/BroadInteractor.hpp>
 #include <yade/core/MetaBody.hpp>
 #include <vector>
@@ -16,26 +17,87 @@
 
 using namespace std;
 
-class SpheresFactory : public StandAloneEngine {
+/// @brief Produces spheres over the course of a simulation. 
+class SpheresFactory : public PeriodicEngine {
 public:
 
 	SpheresFactory();
 	virtual ~SpheresFactory();
 
+	/// @brief Create one sphere per call.
 	virtual void action(MetaBody*);
 
+	/// @brief The geometry of the surface on which spheres will be placed. 
 	vector<body_id_t> factoryFacets; 
-	string labelBroadInteractor;
 
-protected:
+	/// @brief Max attemps to place sphere.
+	/// If placing the sphere in certain random position would cause an overlap with any other physical body in the model, SpheresFactory will try to find another position. Default 20 attempts allow.
+	int maxAttempts; 
+
+	/// @brief Mean radius of spheres.
+	Real radius; 
+
+	/// @brief Half size of a radii distribution interval.
+	/// New sphere will have random radius within the range radius±radiusRange.
+	Real radiusRange;
+
+	/// @brief Mean velocity of spheres.
+	Vector3r velocity;
+
+	/// @brief Half size of a velocities distribution interval.
+	/// New sphere will have random velocity within the range velocity±velocityRange.
+	Vector3r velocityRange;
+	
+	/// @brief Mean angularVelocity of spheres.
+	Vector3r angularVelocity;
+
+	/// @brief Half size of a angularVelocity distribution interval.
+	/// New sphere will have random angularVelocity within the range angularVelocity±angularVelocityRange.
+	Vector3r angularVelocityRange;
+
+	/// @brief Young modulus.
+	Real young;
+	/// @brief Poisson ratio.
+	Real poisson;
+	/// @brief Density of material.
+	Real density;
+	/// @brief Friction angle (radians).
+	Real frictionAngle;
+	/// @brief Color.
+	Vector3r color;
+
+private:
+	/// @brief Pointer to BroadInteractor.
+	/// It is necessary in order to probe the bounding volume for new sphere.
 	BroadInteractor* bI;
+	
+	/// @brief Pointer to InteractionGeometryMetaEngine.
+	/// It is necessary in order to detect a real overlap with other bodies.
+	InteractionGeometryMetaEngine* iGME;
+
 	bool first_run;
 
-	void createSphere(shared_ptr<Body>& body, const Vector3r& position, Real radius);
+	void createSphere(shared_ptr<Body>& body, const Vector3r& position, Real r);
 
+	typedef	boost::variate_generator<boost::minstd_rand,boost::uniform_int<> > RandomInt;
+	shared_ptr<RandomInt> randomFacet;
+
 	DECLARE_LOGGER;
 
-	REGISTER_ATTRIBUTES(StandAloneEngine,(factoryFacets)(labelBroadInteractor))
+	REGISTER_ATTRIBUTES(PeriodicEngine,
+			(factoryFacets)
+			(maxAttempts)
+			(radius)
+			(radiusRange)
+			(velocity)
+			(velocityRange)
+			(angularVelocity)
+			(angularVelocityRange)
+			(young)
+			(poisson)
+			(density)
+			(frictionAngle)
+			(color))
 	REGISTER_CLASS_AND_BASE(SpheresFactory, StandAloneEngine);
 
 };

Modified: trunk/pkg/common/SConscript
===================================================================
--- trunk/pkg/common/SConscript	2009-01-25 04:38:29 UTC (rev 1640)
+++ trunk/pkg/common/SConscript	2009-01-25 14:28:37 UTC (rev 1641)
@@ -153,7 +153,7 @@
 	#	CPPPATH=env['CPPPATH']+['Engine/StandAloneEngine', '$PREFIX/include', '/home/bruno/micromacro/KdevMicroMacro/src']),
     
 	env.SharedLibrary('SpheresFactory',['Engine/StandAloneEngine/SpheresFactory.cpp'],
-		LIBS=env['LIBS']+['AABB','InteractingSphere','InteractingFacet','Sphere','BodyMacroParameters','PersistentSAPCollider']),
+		LIBS=env['LIBS']+['AABB','InteractingSphere','Facet','Sphere','BodyMacroParameters','InteractionGeometryMetaEngine']),
 	env.SharedLibrary('SpatialQuickSortCollider',['Engine/StandAloneEngine/SpatialQuickSortCollider.cpp']),
 	env.SharedLibrary('PersistentSAPCollider',['Engine/StandAloneEngine/PersistentSAPCollider.cpp']),
 	env.SharedLibrary('DistantPersistentSAPCollider',['Engine/StandAloneEngine/DistantPersistentSAPCollider.cpp']),