示例#1
0
void CTiglExportBrep::AddConfiguration(CCPACSConfiguration& config)
{
    // Export all wings of the configuration
    for (int w = 1; w <= config.GetWingCount(); w++) {
        CCPACSWing& wing = config.GetWing(w);

        for (int i = 1; i <= wing.GetSegmentCount(); i++) {
            CCPACSWingSegment& segment = (tigl::CCPACSWingSegment &) wing.GetSegment(i);
            PNamedShape loft = segment.GetLoft();
            AddShape(loft);
        }
    }

    // Export all fuselages of the configuration
    for (int f = 1; f <= config.GetFuselageCount(); f++) {
        CCPACSFuselage& fuselage = config.GetFuselage(f);

        for (int i = 1; i <= fuselage.GetSegmentCount(); i++) {
            CCPACSFuselageSegment& segment = (tigl::CCPACSFuselageSegment &) fuselage.GetSegment(i);
            PNamedShape loft = segment.GetLoft();
            AddShape(loft);
        }
    }

    CCPACSFarField& farfield = config.GetFarField();
    if (farfield.GetFieldType() != NONE) {
        AddShape(farfield.GetLoft());
    }
}
示例#2
0
int Model::DivideShape(TreeObject *parent, Shape *shape, string filename)
{
  Shape *upper = new Shape();
  Shape *lower = new Shape();
  Matrix4d T = Matrix4d::IDENTITY;;//FIXME! objtree.GetSTLTransformationMatrix(parent);
  int num = shape->divideAtZ(0, upper, lower, T);
  if (num<2) return num;
  else if (num==2) {
    AddShape(parent, upper, filename+_("_upper") ,false);
    AddShape(parent, lower, filename+_("_lower") ,false);
  }
  return num;
}
示例#3
0
// Appends the master shapes from other to this.
void ShapeTable::AppendMasterShapes(const ShapeTable& other) {
  for (int s = 0; s < other.shape_table_.size(); ++s) {
    if (other.shape_table_[s]->destination_index() < 0) {
      AddShape(*other.shape_table_[s]);
    }
  }
}
void BulletPhysics::AddPointCloud(Vec3* verts, int numPoints, WeakGameObjectPtr pGameObject, const std::string& densityStr, const std::string& physicsMaterial)
{
	// used to create a convex mesh shape
	StrongGameObjectPtr pStrongObject = MakeStrongPtr(pGameObject);
	if (!pStrongObject)
	{
		CB_ERROR("Must attach a game object to the point cloud");
		return;
	}

	btConvexHullShape* shape = new btConvexHullShape();
	
	// add points to the shape one at a time
	for (int i = 0; i < numPoints; i++)
	{
		shape->addPoint(Vec3_to_btVector3(verts[i]));
	}

	// approximate mass using bounding box
	btVector3 aabbMin(0, 0, 0), aabbMax(0, 0, 0);
	shape->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);

	const btVector3 aabbExtents = aabbMax - aabbMin;
	float specificGravity = LookupSpecificGravity(densityStr);
	const float volume = aabbExtents.x() * aabbExtents.y() * aabbExtents.z();
	const btScalar mass = volume * specificGravity;

	AddShape(pStrongObject, shape, mass, physicsMaterial);
}
示例#5
0
void Model::ReadStl(Glib::RefPtr<Gio::File> file, filetype_t ftype)
{
  bool autoplace = settings.Misc.ShapeAutoplace;
  string path = file->get_path();
  vector<Shape*> shapes = ReadShapes(file, 0, ftype);
  if (shapes.size()==1){
    AddShape(NULL, shapes.front(), shapes.front()->filename, autoplace);
  }
  else for (uint i=0;i<shapes.size();i++){
      // do not autoplace to keep saved positions
      AddShape(NULL, shapes[i], shapes[i]->filename, false);
    }
  shapes.clear();
  ModelChanged();
  return;
}
示例#6
0
// Square enemy
//------------------------------
Square::Square( const Vec2& position, fixed rotation )
: Enemy( position, 4 )
, _dir()
, _timer( z_rand() % 80 + 40 )
{
    AddShape( new Box( Vec2(), 10, 10, 0x33ff33ff, 0, ENEMY | VULNERABLE ) ); _dir.SetPolar( rotation, M_ONE );
    SetScore( 25 );
    SetBoundingWidth( 15 );
    SetEnemyValue( 2 );
}
示例#7
0
int Model::MergeShapes(TreeObject *parent, const vector<Shape*> shapes)
{
  Shape * shape = new Shape();
  for (uint s = 0; s <  shapes.size(); s++) {
    vector<Triangle> str = shapes[s]->getTriangles(shapes[s]->transform3D.transform);
    shape->addTriangles(str);
  }
  AddShape(parent, shape, "merged", true);
  return 1;
}
示例#8
0
BShape&
BShape::operator=(const BShape& other)
{
	if (this != &other) {
		Clear();
		AddShape(&other);
	}

	return *this;
}
示例#9
0
// Tractor beam enemy
//------------------------------
Tractor::Tractor( const Vec2& position, bool power )
: Enemy( position, 50 )
, _timer( TIMER * 4 )
, _dir( 0, 0 )
, _power( power )
, _ready( false )
, _spinning( false )
{
    AddShape( new Polygram( Vec2( 24,  0 ), 12, 6, 0xcc33ccff, 0,  ENEMY | VULNERABLE ) );
    AddShape( new Polygram( Vec2( -24, 0 ), 12, 6, 0xcc33ccff, 0,  ENEMY | VULNERABLE ) );
    AddShape( new Line    ( Vec2( 0,   0 ), Vec2( 24, 0 ), Vec2( -24, 0 ), 0xcc33ccff ) );
    if ( power ) {
        AddShape( new Polystar( Vec2( 24,  0 ), 16, 6, 0xcc33ccff, 0, 0 ) );
        AddShape( new Polystar( Vec2( -24, 0 ), 16, 6, 0xcc33ccff, 0, 0 ) );
    }
    SetScore( 85 + power * 40 );
    SetBoundingWidth( 36 );
    SetDestroySound( Lib::SOUND_PLAYER_DESTROY );
    SetEnemyValue( 10 + ( power ? 2 : 0 ) );
}
示例#10
0
void Model::ReadSVG(Glib::RefPtr<Gio::File> file)
{
  if (is_calculating) return;
  if (is_printing) return;
  bool autoplace = settings.Misc.ShapeAutoplace;
  string path = file->get_path();
  FlatShape * svgshape = new FlatShape(path);
  cerr << svgshape->info() << endl;
  AddShape(NULL, svgshape, path, autoplace);
  ClearLayers();
}
示例#11
0
// Follower enemy
//------------------------------
Follow::Follow( const Vec2& position, fixed radius, int hp )
: Enemy( position, hp )
, _timer( 0 )
, _target( 0 )
{
    AddShape( new Polygon( Vec2(), radius, 4, 0x9933ffff, 0, ENEMY | VULNERABLE ) );
    SetScore( 15 );
    SetBoundingWidth( 10 );
    SetDestroySound( Lib::SOUND_ENEMY_SHATTER );
    SetEnemyValue( 1 );
}
示例#12
0
int Model::SplitShape(TreeObject *parent, Shape *shape, string filename)
{
  vector<Shape*> splitshapes;
  shape->splitshapes(splitshapes, m_progress);
  if (splitshapes.size()<2) return splitshapes.size();
  for (uint s = 0; s <  splitshapes.size(); s++) {
    ostringstream sfn;
    sfn << filename << "_" << (s+1) ;
    AddShape(parent, splitshapes[s], sfn.str(), false);
  }
  return splitshapes.size();
}
示例#13
0
// Wall enemy
//------------------------------
Wall::Wall( const Vec2& position, bool rdir )
: Enemy( position, 10 )
, _dir( 0, 1 )
, _timer( 0 )
, _rotate( false )
, _rdir( rdir )
{
    AddShape( new Box( Vec2(), 10, 40, 0x33cc33ff, 0, ENEMY | VULNERABLE ) );
    SetScore( 20 );
    SetBoundingWidth( 50 );
    SetEnemyValue( 4 );
}
示例#14
0
// Appends the master shapes from other to this.
// If not NULL, shape_map is set to map other shape_ids to this's shape_ids.
void ShapeTable::AppendMasterShapes(const ShapeTable& other,
                                    GenericVector<int>* shape_map) {
  if (shape_map != NULL)
    shape_map->init_to_size(other.NumShapes(), -1);
  for (int s = 0; s < other.shape_table_.size(); ++s) {
    if (other.shape_table_[s]->destination_index() < 0) {
      int index = AddShape(*other.shape_table_[s]);
      if (shape_map != NULL)
        (*shape_map)[s] = index;
    }
  }
}
示例#15
0
// Chaser enemy
//------------------------------
Chaser::Chaser( const Vec2& position )
: Enemy( position, 2 )
, _move( false )
, _timer( TIME )
, _dir()
{
    AddShape( new Polygram( Vec2(), 10, 4, 0x3399ffff, 0, ENEMY | VULNERABLE ) );
    SetScore( 30 );
    SetBoundingWidth( 10 );
    SetDestroySound( Lib::SOUND_ENEMY_SHATTER );
    SetEnemyValue( 2 );
}
void BHSequenceObject::_BuildShapes()
{
	math::rectf rc;
	canvas::PointList opoints;
	opoints.push_back(math::vector2d(-50,30));
	opoints.push_back(math::vector2d(30,30));
	opoints.push_back(math::vector2d(50,-30));
	opoints.push_back(math::vector2d(-30,-30));
	{

		ColoredShape* shape=new ColoredShape();
		video::SColor clrs[]={video::DefaultColors::LightBlue,video::DefaultColors::LightBlue,
			video::DefaultColors::White,video::DefaultColors::White};
		shape->SetColors(clrs);
		shape->SetShapePoints(opoints);

		rc=shape->GetBoundingRect();

		AddShape(shape);
	}
	BHCanvasManager*mngr=(BHCanvasManager*) m_canvasManager;
	if(mngr->GetSymbols())
	{
		TexturedShape* shape=new TexturedShape();
		math::rectf rc(0,0,1,1);
		video::ImageRegion* r=mngr->GetSymbols()->GetRegion(mT("Sequence"));
		if(r)
			rc=r->GetTextureRect();
		shape->SetTexture(mngr->GetSymbols()->GetTexture()->GetTexture(),rc);
		shape->SetShapePoints(opoints);
		AddShape(shape);
	}
	{
		m_label=new TextShape();
		m_label->SetString(core::string(mT("Sequence")));
		m_label->SetRect(rc);
		AddShape(m_label);
	}

}
// When updateing the tree, the manager goes through and deactivates every node in the tree and then reactivates the root.
// It then goes through the entire array of interactive shapes and adds them back into the tree. 
void QuadTreeManager::UpdateQuadtree()
{
	unsigned int treeSize = _quadTree.size();
	for (unsigned int i = 0; i < treeSize; ++i)
	{
		DeactivateNode(_quadTree[i]);
	}
	ActivateNode(_quadTree[0]);
	unsigned int shapesSize = _shapes.size();
	for (unsigned int i = 0; i < shapesSize; ++i)
	{
		AddShape(_shapes[i], 0);
	}
}
示例#18
0
void CTiglExportBrep::AddFusedConfiguration(CCPACSConfiguration& config)
{

    PTiglFusePlane fuser = config.AircraftFusingAlgo();
    fuser->SetResultMode(HALF_PLANE_TRIMMED_FF);
    assert(fuser);

    PNamedShape fusedAirplane = fuser->FusedPlane();
    PNamedShape farField      = fuser->FarField();
    if (!fusedAirplane) {
        throw CTiglError("Error computing fused airplane.", TIGL_NULL_POINTER);
    }

    AddShape(fusedAirplane);
    AddShape(farField);

    // add intersections
    const ListPNamedShape& ints = fuser->Intersections();
    ListPNamedShape::const_iterator it;
    for (it = ints.begin(); it != ints.end(); ++it) {
        AddShape(*it);
    }
}
void RenderManager::GenerateShapes(Shader shader, GLuint vao, int numShapes, GLenum type, GLsizei count)
{
	Collider collider;
	collider.height = 0.035f;
	collider.width = 0.035f;
	for (int i = 0; i < numShapes; ++i)
	{
		Transform transform = Transform();
		transform.position = glm::vec3(glm::linearRand(-1.337f, 1.337f), glm::linearRand(-1.0f, 1.0f), 0.0f);
		glm::vec4 color = glm::vec4(glm::linearRand(0.25f, 0.75f), glm::linearRand(0.25f, 0.75f), glm::linearRand(0.25f, 0.75f), 1.0f);
		transform.scale = glm::vec3(0.025f, 0.025f, 0.01f);
		AddShape(shader, vao, type, count, color, transform, collider);
	}
}
示例#20
0
cpShape*
PhysicsWorld::AddStaticRect(cpFloat width, cpFloat height, cpFloat xPosition, cpFloat yPosition, cpFloat friction)
{
    cpVect verts[4] = { cpv(xPosition - (width / 2.0f), yPosition + (height / 2.0f)), 
        cpv(xPosition + (width / 2.0f), yPosition + (height / 2.0f)), 
        cpv(xPosition + (width / 2.0f), yPosition - (height / 2.0f)), 
        cpv(xPosition - (width / 2.0f), yPosition - (height / 2.0f)) };
    cpShape * boxShape = cpPolyShapeNew(GetStaticBody(), 4, verts, cpvzero);
    
    cpShapeSetFriction(boxShape, friction);
    AddShape(boxShape);
    
    return boxShape;
}
示例#21
0
// Shielder enemy
//------------------------------
Shielder::Shielder( const Vec2& position, bool power )
: Enemy( position, 16 )
, _dir( 0, 1 )
, _timer( 0 )
, _rotate( false )
, _rDir( false )
, _power( power )
{
    AddShape( new Polystar( Vec2(  24,  0 ), 8, 6, 0x006633ff, 0,            VULNSHIELD ) );
    AddShape( new Polystar( Vec2( -24,  0 ), 8, 6, 0x006633ff, 0,            VULNSHIELD ) );
    AddShape( new Polystar( Vec2( 0,   24 ), 8, 6, 0x006633ff, M_PI / M_TWO, VULNSHIELD ) );
    AddShape( new Polystar( Vec2( 0,  -24 ), 8, 6, 0x006633ff, M_PI / M_TWO, VULNSHIELD ) );
    AddShape( new Polygon ( Vec2(  24,  0 ), 8, 6, 0x33cc99ff, 0,            0 ) );
    AddShape( new Polygon ( Vec2( -24,  0 ), 8, 6, 0x33cc99ff, 0,            0 ) );
    AddShape( new Polygon ( Vec2( 0,   24 ), 8, 6, 0x33cc99ff, M_PI / M_TWO, 0 ) );
    AddShape( new Polygon ( Vec2( 0,  -24 ), 8, 6, 0x33cc99ff, M_PI / M_TWO, 0 ) );

    AddShape( new Polystar( Vec2( 0,    0 ), 24, 4,                      0x006633ff, 0, 0 ) );
    AddShape( new Polygon ( Vec2( 0,    0 ), 14, 8, power ? 0x33cc99ff : 0x006633ff, 0, ENEMY | VULNERABLE ) );
    SetScore( 60 + _power * 40 );
    SetBoundingWidth( 36 );
    SetDestroySound( Lib::SOUND_PLAYER_DESTROY );
    SetEnemyValue( 8 + ( power ? 2 : 0 ) );
}
示例#22
0
// Expands all the classes/fonts in the shape individually to build
// a ShapeTable.
int ShapeTable::BuildFromShape(const Shape& shape,
                               const ShapeTable& master_shapes) {
  BitVector shape_map(master_shapes.NumShapes());
  for (int u_ind = 0; u_ind < shape.size(); ++u_ind) {
    for (int f_ind = 0; f_ind < shape[u_ind].font_ids.size(); ++f_ind) {
      int c = shape[u_ind].unichar_id;
      int f = shape[u_ind].font_ids[f_ind];
      int master_id = master_shapes.FindShape(c, f);
      if (master_id >= 0) {
        shape_map.SetBit(master_id);
      } else if (FindShape(c, f) < 0) {
        AddShape(c, f);
      }
    }
  }
  int num_masters = 0;
  for (int s = 0; s < master_shapes.NumShapes(); ++s) {
    if (shape_map[s]) {
      AddShape(master_shapes.GetShape(s));
      ++num_masters;
    }
  }
  return num_masters;
}
示例#23
0
BOOL CShapesDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	CRect rect(20,20,120,120);

	CShape* pShapeNew = new CShape(
		black,
		rectangle,
		rect);
	AddShape(pShapeNew);

	return TRUE;
}
示例#24
0
// Follow spawner enemy
//------------------------------
FollowHub::FollowHub( const Vec2& position, bool powerA, bool powerB )
: Enemy( position, 14 )
, _timer( 0 )
, _dir( 0, 0 )
, _count( 0 )
, _powerA( powerA )
, _powerB( powerB )
{
    AddShape( new Polygram( Vec2(), 16, 4, 0x6666ffff, M_PI / M_FOUR, ENEMY | VULNERABLE ) );
    if ( _powerB ) {
        AddShape( new Polystar( Vec2( 16,  0 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
        AddShape( new Polystar( Vec2( -16, 0 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
        AddShape( new Polystar( Vec2( 0,  16 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
        AddShape( new Polystar( Vec2( 0, -16 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
    }
    AddShape( new Polygon( Vec2( 16,  0 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
    AddShape( new Polygon( Vec2( -16, 0 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
    AddShape( new Polygon( Vec2( 0,  16 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
    AddShape( new Polygon( Vec2( 0, -16 ), 8, 4, 0x6666ffff, M_PI / M_FOUR ) );
    SetScore( 50 + _powerA * 10 + _powerB * 10 );
    SetBoundingWidth( 16 );
    SetDestroySound( Lib::SOUND_PLAYER_DESTROY );
    SetEnemyValue( 6 + ( powerA ? 2 : 0 ) + ( powerB ? 2 : 0 ) );
}
示例#25
0
void BulletPhysics::AddBox(const Vec3& dimensions, WeakGameObjectPtr pGameObject, const std::string& densityStr, const std::string& physicsMaterial)
{
	StrongGameObjectPtr pStrongObject = MakeStrongPtr(pGameObject);
	if (!pStrongObject)
	{
		CB_ERROR("Must attach a game object to the box");
		return;
	}

	// create box collider
	btBoxShape* boxShape = new btBoxShape(Vec3_to_btVector3(dimensions));

	// calculate mass using specific gravity (density)
	float specificGravity = LookupSpecificGravity(densityStr);
	const float volume = dimensions.x * dimensions.y * dimensions.z;
	const btScalar mass = volume * specificGravity;

	AddShape(pStrongObject, boxShape, mass, physicsMaterial);
}
示例#26
0
void BulletPhysics::AddSphere(float radius, WeakGameObjectPtr pGameObject, const std::string& densityStr, const std::string& physicsMaterial)
{
	StrongGameObjectPtr pStrongObject = MakeStrongPtr(pGameObject);
	if (!pStrongObject)
	{
		CB_ERROR("Must attach a game object to the sphere");
		return;
	}

	// create a sphere collider
	btSphereShape* sphereShape = new btSphereShape(radius);

	// calculate mass using specific gravity (density)
	float specificGravity = LookupSpecificGravity(densityStr);
	const float volume = (4.0f / 3.0f) * CB_PI * radius * radius * radius;
	const btScalar mass = volume * specificGravity;

	AddShape(pStrongObject, sphereShape, mass, physicsMaterial);
}
示例#27
0
文件: world.cpp 项目: erik/blocks
WorldShape World::CreateBox(int x, int y, int width, int height, bool isStatic) {
  const float scale(WorldConfig::scale);

  b2BodyDef bodyDef;
  bodyDef.position.Set((x + width / 2) / scale, (y + height / 2) / scale);

  if(!isStatic) {
    bodyDef.type = b2_dynamicBody;
  } else {
    // protect against tunneling with static objects
    bodyDef.bullet = true;
  }

  b2Body* body = CreateBody(bodyDef);

  WorldShape shape = WorldShape::AsBox(body, width / scale, height / scale, isStatic);

  AddShape(shape);
  return shape;
}
示例#28
0
void CProtoHapticDoc::undo()
{
	if(m_historyCount>0) {
		CProtoHapticDoc* lastState= popHistory();

		int i;
		int max= m_shapeCount;
		for(i= 0; i<max; i++)
		{
			RemoveShape(m_shapes[0]);
		}

		for(i= 0; i<lastState->m_shapeCount; i++) {
			AddShape(lastState->m_shapes[i]);
		}

		for(i= 0; i<lastState->m_memoCount; i++) {
			m_memos[i]= lastState->m_memos[i];
		}
		m_memoCount= lastState->m_memoCount;
	}
}
示例#29
0
// Expands all the classes/fonts in the shape individually to build
// a ShapeTable.
int ShapeTable::BuildFromShape(const Shape& shape,
                               const ShapeTable& master_shapes) {
  int num_masters = 0;
  for (int u_ind = 0; u_ind < shape.size(); ++u_ind) {
    for (int f_ind = 0; f_ind < shape[u_ind].font_ids.size(); ++f_ind) {
      int c = shape[u_ind].unichar_id;
      int f = shape[u_ind].font_ids[f_ind];
      if (FindShape(c, f) < 0) {
        int shape_id = AddShape(c, f);
        int master_id = master_shapes.FindShape(c, f);
        if (master_id >= 0 && shape.size() > 1) {
          const Shape& master = master_shapes.GetShape(master_id);
          if (master.IsSubsetOf(shape) && !shape.IsSubsetOf(master)) {
            // Add everything else from the master shape.
            shape_table_[shape_id]->AddShape(master);
            ++num_masters;
          }
        }
      }
    }
  }
  return num_masters;
}
示例#30
0
void ExplainCanvas::SetExplainString(const wxString &str)
{
	Clear();

	ExplainShape *last = 0;
	int maxLevel = 0;

	wxStringTokenizer lines(str, wxT("\n"));

	while (lines.HasMoreTokens())
	{
		wxString tmp = lines.GetNextToken();
		wxString line = tmp.Strip(wxString::both);

		int braceCount = 0;
		do
		{
			const wxChar *cp = line.c_str();
			while (*cp)
			{
				if (*cp == '(')
					braceCount++;
				else if (*cp == ')')
					braceCount--;
				cp++;
			}
			if (braceCount > 0)
			{
				wxString tmp = lines.GetNextToken();
				line += wxT(" ") + tmp.Strip(wxString::both);
				braceCount = 0;
			}
			else
				break;
		}
		while (lines.HasMoreTokens());

		long level = (tmp.Length() - line.Length() + 4) / 6;

		if (last)
		{
			if (level)
			{
				if (line.Left(4) == wxT("->  "))
					line = line.Mid(4);
				else
				{
					last->SetCondition(line);
					continue;
				}
			}

			while (last && level <= last->GetLevel())
				last = last->GetUpper();
		}


		ExplainShape *s = ExplainShape::Create(level, last, line);
		if (!s)
			continue;
		s->SetCanvas(this);
		InsertShape(s);
		s->Show(true);

		if (level > maxLevel)
			maxLevel = level;

		if (!last)
			rootShape = s;
		last = s;
	}


	int x0 = (int)(rootShape->GetWidth() * 3);
	int y0 = (int)(rootShape->GetHeight() * 3 / 2);
	int xoffs = (int)(rootShape->GetWidth() * 3);
	int yoffs = (int)(rootShape->GetHeight() * 5 / 4);

	wxNode *current = GetDiagram()->GetShapeList()->GetFirst();
	while (current)
	{
		ExplainShape *s = (ExplainShape *)current->GetData();

		if (!s->totalShapes)
			s->totalShapes = 1;
		if (s->GetUpper())
			s->GetUpper()->totalShapes += s->totalShapes;
		current = current->GetNext();
	}

	current = GetDiagram()->GetShapeList()->GetLast();
	while (current)
	{
		ExplainShape *s = (ExplainShape *)current->GetData();

		s->SetX(y0 + (maxLevel - s->GetLevel()) * xoffs);
		ExplainShape *upper = s->GetUpper();

		if (upper)
		{
			s->SetY(upper->GetY() + upper->usedShapes * yoffs);
			upper->usedShapes += s->totalShapes;

			wxLineShape *l = new ExplainLine(s, upper);
			l->Show(true);
			AddShape(l);
		}
		else
		{
			s->SetY(y0);
		}

		current = current->GetPrevious();
	}

#define PIXPERUNIT  20
	int w = (maxLevel * xoffs + x0 * 2 + PIXPERUNIT - 1) / PIXPERUNIT;
	int h = (rootShape->totalShapes * yoffs + y0 * 2 + PIXPERUNIT - 1) / PIXPERUNIT;

	SetScrollbars(PIXPERUNIT, PIXPERUNIT, w, h);
}