Пример #1
0
void NumberValue::verifyUnits(const NumberValue& n) {
  if (type == Value::DIMENSION && n.type == Value::DIMENSION &&
      getUnit().compare(n.getUnit()) != 0) {
    setValue(convert(n.getUnit()));
    setUnit(n.getUnit());
  }
}
Пример #2
0
Value* Color::substract(Value* v) {
  Color* c;
  NumberValue* n;
  
  if (v->type == COLOR) {
    c = static_cast<Color*>(v);
    color[RGB_RED] = color[RGB_RED] > c->getRed() ?
      color[RGB_RED] - c->getRed() : 0;
    color[RGB_GREEN] = color[RGB_GREEN] > c->getGreen() ?
      color[RGB_GREEN] - c->getGreen() : 0;
    color[RGB_BLUE] = color[RGB_BLUE] > c->getBlue() ?
      color[RGB_BLUE] - c->getBlue() : 0;
  } else if (v->type == Value::NUMBER ||
             v->type == Value::PERCENTAGE ||
             v->type == Value::DIMENSION) {
    n = static_cast<NumberValue*>(v);
    color[RGB_RED] -= n->getValue();
    color[RGB_GREEN] -= n->getValue();
    color[RGB_BLUE] -= n->getValue();
  } else {
    throw new ValueException("You can only substract a color or \
a number from a color.");
  }
  valueChanged = true;
  return this;
}
Пример #3
0
Value* NumberValue::tan(const vector<const Value*> &args) {
  if (args[0]->type != Value::NUMBER &&
      args[0]->type != Value::DIMENSION) {
    throw new ValueException("tan() only works on numbers "
                             "or dimensions", *args[0]->getTokens());
  }
  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  double val = n->getValue();
  std::string unit;
    
  if (n->type == Value::DIMENSION) {
    unit = n->getUnit();
    if(unit.compare("rad") != 0 &&
       unit.compare("deg") != 0 &&
       unit.compare("grad") != 0 &&
       unit.compare("turn") != 0) {
      throw new ValueException("ta() requires rad, deg, "
                               "grad or turn units.", *args[0]->getTokens());
    }
    val = UnitValue::angleToRad(val, unit);
  }

  n->setValue(std::tan(val));
  n->type = Value::NUMBER;
  n->setUnit("");
  return n;
}    
Пример #4
0
Node* CylinderSurfaceModule::evaluate(Context* ctx)
{
	NumberValue* heightValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	decimal h=1.0;
	if(heightValue)
		h=heightValue->getNumber();

	NumberValue* rValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,1));
	decimal r=1.0;
	if(rValue)
		r=rValue->getNumber();

	Value* centerValue=getParameterArgument(ctx,2);
	bool center=false;

	if(centerValue)
		center=centerValue->isTrue();

	decimal z1,z2;
	z1 = 0.0;
	z2 = h;

	Fragment* fg = Fragment::createFragment(ctx);
	int f = fg->getFragments(r);
	delete fg;

	QList<Point> c1=getCircle(r,f,z1);
	QList<Point> c2=getCircle(r,f,z2);

	PrimitiveNode* p=new PrimitiveNode(reporter);
	p->setChildren(ctx->getInputNodes());

	foreach(Point pt,c1) {
		p->createVertex(pt);
	}
Пример #5
0
Value* Color::multiply(Value* v) {
  Color* c;
  NumberValue* n;
  int result;
  
  if (v->type == COLOR) {
    c = static_cast<Color*>(v);
    result = color[RGB_RED] * c->getRed();
    color[RGB_RED] = max(min(result, 255), 0);
    result = color[RGB_GREEN] * c->getGreen();
    color[RGB_GREEN] = max(min(result, 255), 0);
    result = color[RGB_BLUE] * c->getBlue();
    color[RGB_BLUE] = max(min(result, 255), 0);
  } else if (v->type == Value::NUMBER ||
             v->type == Value::PERCENTAGE ||
             v->type == Value::DIMENSION) {
    n = static_cast<NumberValue*>(v);
    color[RGB_RED] *= n->getValue();
    color[RGB_GREEN] *= n->getValue();
    color[RGB_BLUE] *= n->getValue();
  } else {
    throw new ValueException("You can only multiply a color by a \
color or a number.");
  }
  valueChanged = true;
  return this;
}
Пример #6
0
Value* Color::add(Value* v) {
  Color* c;
  NumberValue* n;
  StringValue* s;
  string* str;
  
  if (v->type == COLOR) {
    c = static_cast<Color*>(v);
    color[RGB_RED] += c->getRed();
    color[RGB_GREEN] += c->getGreen();
    color[RGB_BLUE] += c->getBlue();
  } else if (v->type == NUMBER ||
             v->type == PERCENTAGE ||
             v->type == DIMENSION) {
    n = static_cast<NumberValue*>(v);
    color[RGB_RED] += n->getValue();
    color[RGB_GREEN] += n->getValue();
    color[RGB_BLUE] += n->getValue();
  } else if(v->type == STRING) {
    str = this->getTokens()->toString();
    s = new StringValue(new Token(*str, Token::STRING),
                        ((StringValue*)v)->getQuotes());
    s->add(v);
    delete str;
    return s;
  }
  valueChanged = true;
  return this;
}
Пример #7
0
Value* NumberValue::atan(const vector<const Value*> &args) {
  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);

  n->setValue(std::atan(n->getValue()));
  n->setUnit("rad");
  n->type = Value::DIMENSION;
  return n;
}   
Пример #8
0
void NumberValue<T, TypeID>::setVal(AbstractValue* val)
{
    if ( this->type() != val->type() )
        throw "Variable must be the same type";
    
    NumberValue<T, TypeID>* numVal = dynamic_cast<NumberValue<T, TypeID>*>(val);
    setValue(numVal->value());
}
Пример #9
0
Value* NumberValue::abs(const vector<const Value*> &args) {
  if (!NumberValue::isNumber(*args[0]))
    throw new ValueException("abs() only works on numeric "
                             "values", *args[0]->getTokens());

  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  n->setValue(fabs(n->getValue()));
  return n;
}
Пример #10
0
boost::shared_ptr<AbstractValue> NumberValue<T, TypeID>::clone()
{
    NumberValue<T, TypeID>* numVal = new NumberValue<T, TypeID>();
    numVal->setValue(this->value());
    
    boost::shared_ptr<AbstractValue> ptr(numVal);
    
    return ptr;
}
Пример #11
0
Value* NumberValue::pow(const vector<const Value*> &args) {
  if (!NumberValue::isNumber(*args[0]))
    throw new ValueException("pow() only works on numeric values",
                             *args[0]->getTokens());

  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  double exp = ((const NumberValue*)args[1])->getValue();
  
  n->setValue(std::pow(n->getValue(), exp));
  return n;
}    
Пример #12
0
Value* NumberValue::mod(const vector<const Value*> &args) {
  if (!NumberValue::isNumber(*args[0]) ||
      !NumberValue::isNumber(*args[1]))
    throw new ValueException("mod() only works on numeric values",
                             *args[0]->getTokens());

  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  double val2 = ((NumberValue*)args[1])->getValue();

  n->setValue(std::fmod(n->getValue(), val2));
  return n;
}    
Пример #13
0
Value* NumberValue::floor(const vector<const Value*> &args) {
  NumberValue *n;
  
  if (!NumberValue::isNumber(*args[0]))
    throw new ValueException("floor() only works on numeric "
                             "values", *args[0]->getTokens());

  n = new NumberValue(*static_cast<const NumberValue*>(args[0]));

  double val = n->getValue();
  n->setValue(std::floor(val));
  return n;
}  
Пример #14
0
// DIMENSION unit(DIMENSION, UNIT)
Value* NumberValue::unit(const vector<const Value*> &arguments) {
  NumberValue* ret;
  
  if (arguments[0]->type == Value::NUMBER ||
      arguments[0]->type == Value::DIMENSION) {
    ret = new NumberValue(((const NumberValue*)arguments[0])->getValue());
    
    if (arguments.size() > 1) {
      ret->setUnit(((const UnitValue*)arguments[1])->getUnit());
    } else
      ret->setUnit("");
    return ret;
  } else 
    throw new ValueException("argument 1 has to be a number "
                             "or dimension", *arguments[0]->getTokens());
}
Пример #15
0
Value* NumberValue::round(const vector<const Value*> &args) {
  if (!NumberValue::isNumber(*args[0]))
    throw new ValueException("round() only works on numeric "
                             "values", *args[0]->getTokens());

  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  double val = n->getValue();
  double decimalplaces = 0;
  
  if (args.size() > 1)
    decimalplaces = ((const NumberValue*)args[1])->getValue();

  val = val * std::pow(10, decimalplaces);
  val = std::floor(val + 0.5);
  val = val / std::pow(10, decimalplaces);
  n->setValue(val);
  return n;
}  
Пример #16
0
void NumberValue::setType(const NumberValue &n) {
  type = n.type;
  if (n.type == DIMENSION)
    setUnit(n.getUnit());
  else if (n.type == PERCENTAGE) 
    tokens.front().type = Token::PERCENTAGE;
  else if (n.type == NUMBER) {
    setUnit("");
  }
}
Пример #17
0
Node* CylinderSurfaceModule::evaluate(Context* ctx)
{
	NumberValue* heightValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	double h=1.0;
	if(heightValue)
		h=heightValue->getNumber();

	NumberValue* rValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,1));
	double r=1.0;
	if(rValue)
		r=rValue->getNumber();

	Value* centerValue=getParameterArgument(ctx,2);
	bool center=false;
	if(centerValue)
		center=centerValue->isTrue();

	double z1,z2;
	if(center) {
		z1 = -h/2;
		z2 = +h/2;
	} else {
		z1 = 0.0;
		z2 = h;
	}

	int f = getFragments(r,ctx);
	Polygon c1 = getCircle(r,f,z1);
	Polygon c2 = getCircle(r,f,z2);
	PrimitiveNode* p = new PrimitiveNode();

	for(int i=0; i<f; i++) {
		int j=(i+1)%f;
		p->createPolygon();
		p->appendVertex(c1.at(i));
		p->appendVertex(c2.at(i));
		p->appendVertex(c2.at(j));
		p->appendVertex(c1.at(j));
	}

	return p;
}
Пример #18
0
void Worker::generation()
{
	Script* s=parse("reprap.rcam",NULL,true);

	TreeEvaluator* e = new TreeEvaluator(reporter);
	decimal height=getBoundsHeight();
	QList<Argument*> args=getArgs(height);
	Callback* c = addCallback("layers",s,args);
	s->accept(*e);

	NumberValue* v = dynamic_cast<NumberValue*>(c->getResult());
	if(v) {
		reporter->reportMessage(tr("Layers: %1").arg(v->getValueString()));

		int itterations=v->getNumber();
		Instance* m=addProductInstance("manufacture",s);
		for(int i=0; i<=itterations; i++) {
			if(i>0) {
				e = new TreeEvaluator(reporter);
			}
			reporter->reportMessage(tr("Manufacturing layer: %1").arg(i));

			QList<Argument*> args=getArgs(i);
			m->setArguments(args);

			s->accept(*e);
			Node* n=e->getRootNode();

			NodeEvaluator* ne = new NodeEvaluator(reporter);
			n->accept(*ne);
			delete n;

			primitive=ne->getResult();
			delete ne;

			update();
		}
	}
	delete e;
	delete s;
}
Пример #19
0
Value* NumberValue::add(const Value &v) const {
  const NumberValue* n;
  const StringValue* s;
  NumberValue* nret;
  StringValue* sret;
  
  if (isNumber(v)) {
    n = static_cast<const NumberValue*>(&v);
    nret = new NumberValue(getValue());
    if (type == NUMBER) 
      nret->setType(*n);
    else {
      nret->setType(*this);
      nret->verifyUnits(*n);
    }
    nret->setValue(nret->getValue() + n->getValue());
    
    return nret;
    
  } else if (v.type == COLOR) {
    return static_cast<const Color*>(&v)->add(*this);
    
  } else if (v.type == STRING) {
    s = static_cast<const StringValue*>(&v);
    sret = new StringValue(*this, s->getQuotes());
    sret->append(v);
    return sret;

  } else {
    throw new ValueException("Unsupported type.", *this->getTokens());
  }
}
Пример #20
0
Value* NumberValue::multiply(const Value &v) const {
  const NumberValue* n;
  NumberValue* ret;
  
  if (isNumber(v)) {
    n = static_cast<const NumberValue*>(&v);
    ret = new NumberValue(getValue());
    
    if (type == NUMBER) 
      ret->setType(*n);
    else {
      ret->setType(*this);
      ret->verifyUnits(*n);
    }
    ret->setValue(ret->getValue() * n->getValue());
    return ret;

  } else if (v.type == COLOR) {
    return static_cast<const Color*>(&v)->multiply(*this);
    
  } else if(v.type == STRING) {
    return static_cast<const StringValue*>(&v)->multiply(*this);

  } else {
    throw new ValueException("Unsupported type.", *this->getTokens());
  }
}
Пример #21
0
Value* Color::divide(Value* v) {
  Color* c;
  NumberValue* n;
  
  if (v->type == COLOR) {
    c = static_cast<Color*>(v);
    color[RGB_RED] /= c->getRed();
    color[RGB_GREEN] /= c->getGreen();
    color[RGB_BLUE] /= c->getBlue();
  } else if (v->type == Value::NUMBER ||
             v->type == Value::PERCENTAGE ||
             v->type == Value::DIMENSION){
    n = static_cast<NumberValue*>(v);
    color[RGB_RED] /= n->getValue();
    color[RGB_GREEN] /= n->getValue();
    color[RGB_BLUE] /= n->getValue();
  } else {
    throw new ValueException("You can only divide a color by a \
color or a number.");
  }
  valueChanged = true;
  return this;
}
Пример #22
0
Value* NumberValue::convert(const vector<const Value*> &args) {
  if (!NumberValue::isNumber(*args[0]))
    throw new ValueException("convert() only works on numeric values",
                             *args[0]->getTokens());  
  if (args[1]->type != Value::STRING &&
      args[1]->type != Value::UNIT) {
    throw new ValueException("convert() requires a unit \
(or unit as a string)",
                             *args[1]->getTokens());
  }

  NumberValue* n = new NumberValue(*(const NumberValue*)args[0]);
  std::string unit;
    
  if (args[1]->type == Value::STRING)
    unit = ((const StringValue*)args[1])->getString();
  else
    unit.append(((const UnitValue*)args[1])->getUnit());

  n->setValue(n->convert(unit));
  n->setUnit(unit);
  return n;
}
Пример #23
0
Node* CylinderModule::evaluate(Context* ctx)
{
	NumberValue* heightValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	decimal h=1.0;
	if(heightValue)
		h=heightValue->getNumber();

	NumberValue* r1Value = dynamic_cast<NumberValue*>(ctx->getArgument(1,"radius1"));
	NumberValue* r2Value = dynamic_cast<NumberValue*>(ctx->getArgument(2,"radius2"));
	BooleanValue* centerValue;

	decimal r1=1.0,r2=1.0;
	if(!r1Value) {
		NumberValue* rValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,1));
		centerValue = dynamic_cast<BooleanValue*>(getParameterArgument(ctx,2));
		if(rValue) {
			r1=r2=rValue->getNumber();
		} else {
			NumberValue* dValue = dynamic_cast<NumberValue*>(ctx->getArgument(1,"diameter"));
			if(dValue)
				r1=r2=(dValue->getNumber()/2.0);
		}
	} else {
		if(r1Value)
			r1=r1Value->getNumber();
		if(r2Value)
			r2=r2Value->getNumber();
		else
			r2=r1;
		centerValue = dynamic_cast<BooleanValue*>(ctx->getArgument(3,"center"));
	}
	bool center = false;
	if(centerValue)
		center=centerValue->isTrue();

	decimal z1,z2;
	z1 = 0.0;
	z2 = h;

	decimal r=fmax(r1,r2);
	Fragment fg=getSpecialVariables(ctx);
	int f = fg.getFragments(r);

	QList<Point> c1=getCircle(r1,f,z1);
	QList<Point> c2=getCircle(r2,f,z2);

	PrimitiveNode* p = new PrimitiveNode();

	int n=0;
	Polygon* pg;
	if(r1>0) {
		pg=p->createPolygon();
		foreach(Point pt,c1) {
			p->createVertex(pt);
			pg->append(n++);
		}
Пример #24
0
Value* NumberValue::divide(const Value &v) const {
  const NumberValue* n;
  NumberValue* ret;

  if (isNumber(v)) {
    n = static_cast<const NumberValue*>(&v);
    ret = new NumberValue(getValue());
    
    if (type == NUMBER) 
      ret->setType(*n);
    else {
      ret->setType(*this);
      ret->verifyUnits(*n);
    }
    ret->setValue(ret->getValue() / n->getValue());
    
    return ret;
  } else
    throw new ValueException("You can only divide a number "
                             "by a *number*.", *this->getTokens());
}
Пример #25
0
Value* NumberValue::substract(const Value &v) const {
  const NumberValue* n;
  NumberValue* ret;
  
  if (isNumber(v)) {
    n = static_cast<const NumberValue*>(&v);
    ret = new NumberValue(getValue());

    if (type == NUMBER) 
      ret->setType(*n);
    else {
      ret->setType(*this);
      ret->verifyUnits(*n);
    }

    ret->setValue(ret->getValue() - n->getValue());

    return ret;
  } else
    throw new ValueException("You can only substract a "
                             "*number* from a number.", *this->getTokens());
}
Пример #26
0
Node* SphereModule::evaluate(Context* ctx)
{
	NumberValue* rValue=dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	Value* centerValue=getParameterArgument(ctx,1);

	bool center=true;
	if(centerValue)
		center=centerValue->isTrue();

	double r=1.0;
	if(rValue) {
		r=rValue->getNumber();
	} else {
		NumberValue* dValue = dynamic_cast<NumberValue*>(ctx->getArgument(0,"diameter"));
		if(dValue)
			r=(dValue->getNumber()/2.0);
	}

	int f = getFragments(r,ctx);
	int ringCount=f/2;

	QList<Polygon> rings;
	for(int i=0; i<ringCount; i++) {
		double phi = (M_PI*(i+0.5)) / ringCount;
		double r2 = r*sin(phi);
		double z = r*cos(phi)+!center*r;
		Polygon c = getCircle(r2,f,z);
		rings.append(c);
	}

	PrimitiveNode* p = new PrimitiveNode();

	p->createPolygon();
	for(int i=0; i<f; i++)
		p->appendVertex(rings.at(0).at(i));

	for(int i = 0; i < ringCount-1; i++) {
		Polygon r1 = rings.at(i);
		Polygon r2 = rings.at(i+1);
		int r1i = 0, r2i = 0;
		while(r1i < f || r2i < f) {
			if(r1i >= f)
				goto next_r2;
			if(r2i >= f)
				goto next_r1;
			if((double)r1i / f <
					(double)r2i / f) {
next_r1:
				p->createPolygon();
				int r1j = (r1i+1) % f;
				p->prependVertex(r1.at(r1i));
				p->prependVertex(r1.at(r1j));
				p->prependVertex(r2.at(r2i % f));
				r1i++;
			} else {
next_r2:
				p->createPolygon();
				int r2j = (r2i+1) % f;
				p->appendVertex(r2.at(r2i));
				p->appendVertex(r2.at(r2j));
				p->appendVertex(r1.at(r1i % f));
				r2i++;
			}
		}
	}

	p->createPolygon();
	for(int i=0; i<f; i++)
		p->prependVertex(rings.at(ringCount-1).at(i));

	return p;
}
Пример #27
0
Node* ConeModule::evaluate(Context* ctx)
{
	NumberValue* heightValue = dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	NumberValue* r1Value = dynamic_cast<NumberValue*>(getParameterArgument(ctx,1));
	NumberValue* r2Value = dynamic_cast<NumberValue*>(getParameterArgument(ctx,2));
	Value* centerValue = getParameterArgument(ctx,3);

	decimal h=1.0;
	if(heightValue)
		h=heightValue->getNumber();

	decimal r1=0,r2=0;
	if(r1Value)
		r1=r1Value->getNumber();
	if(r2Value)
		r2=r2Value->getNumber();

	bool center = false;
	if(centerValue)
		center=centerValue->isTrue();

	decimal z1,z2;
	z1 = 0.0;
	z2 = h;

	Fragment fg=getSpecialVariables(ctx);
	decimal r=fmax(r1,r2);
	int f = fg.getFragments(r);

	Polygon* p1 = getCircle(r1,f,z1);
	Polygon* p2 = getCircle(r2,f,z2);

	QList<Point> c1=p1->getPoints();
	QList<Point> c2=p2->getPoints();

	PrimitiveNode* p = new PrimitiveNode();

	if(r1 > 0) {
		p->createPolygon();
		foreach(Point pt, c1)
			p->appendVertex(pt);
	}

	if(h==0.0)
		return p;

	for(int i=0; i<f; i++) {
		int j=(i+1)%f;
		if(r1 > 0) {
			p->createPolygon();
			p->appendVertex(c1.at(i));
			p->appendVertex(c2.at(i));
			p->appendVertex(c1.at(j));
		}
		if(r2 > 0) {
			p->createPolygon();
			p->appendVertex(c2.at(i));
			p->appendVertex(c2.at(j));
			p->appendVertex(c1.at(j));
		}
	}

	if(r2 > 0) {
		p->createPolygon();
		foreach(Point pt,c2)
			p->prependVertex(pt);
	}

	if(center) {
		AlignNode* n=new AlignNode();
		n->setCenter(true);
		n->addChild(p);
		return n;
	}

	return p;
}
Пример #28
0
NumberValue::NumberValue(const NumberValue &n) {
  tokens.push_back(n.getTokens()->front());
  this->type = n.type;
}
Пример #29
0
Node* SphereModule::evaluate(Context* ctx)
{
	NumberValue* rValue=dynamic_cast<NumberValue*>(getParameterArgument(ctx,0));
	Value* centerValue=getParameterArgument(ctx,1);

	bool center=true;
	if(centerValue)
		center=centerValue->isTrue();

	decimal r=0.0;
	if(rValue) {
		r=rValue->getNumber();
	} else {
		NumberValue* dValue = dynamic_cast<NumberValue*>(ctx->getArgument(0,"diameter"));
		if(dValue)
			r=(dValue->getNumber()/2.0);
	}
	if(r==0.0)
		return new PointNode();

	Fragment fg=getSpecialVariables(ctx);
	int f = fg.getFragments(r);
	int ringCount=f/2;

	decimal h=center?0.0:r;
	QList<Polygon> rings;
	for(int i=0; i<ringCount; i++) {
		decimal phi = (M_PI*(i+0.5)) / ringCount;
		decimal r2 = r*sin(phi);
		decimal z = r*cos(phi)+h;
		Polygon* c = getCircle(r2,f,z);
		rings.append(*c);
	}

	PrimitiveNode* p = new PrimitiveNode();

	p->createPolygon();
	Polygon top=rings.at(0);
	foreach(Point pt, top.getPoints())
		p->appendVertex(pt);

	for(int i = 0; i < ringCount-1; i++) {
		QList<Point> r1 = rings.at(i).getPoints();
		QList<Point> r2 = rings.at(i+1).getPoints();
		int r1i = 0, r2i = 0;
		while(r1i < f || r2i < f) {
			if(r2i >= f||(decimal)r1i/f<(decimal)r2i/f) {
				p->createPolygon();
				int r1j = (r1i+1) % f;
				p->prependVertex(r1.at(r1i));
				p->prependVertex(r1.at(r1j));
				p->prependVertex(r2.at(r2i % f));
				r1i++;
			} else {
				p->createPolygon();
				int r2j = (r2i+1) % f;
				p->appendVertex(r2.at(r2i));
				p->appendVertex(r2.at(r2j));
				p->appendVertex(r1.at(r1i % f));
				r2i++;
			}
		}
	}

	p->createPolygon();
	Polygon bottom=rings.at(ringCount-1);
	foreach(Point pt, bottom.getPoints())
		p->prependVertex(pt);

	if(center) {
		AlignNode* n=new AlignNode();
		n->setCenter(true);
		n->addChild(p);
		return n;
	}

	return p;
}