Example #1
0
Component CaseFactory::addHoleForPort(const Component & component, double partOuterHeight, const PortDescription & port)
{
    double off_xy = walls + space;

    // u is the vector facing in the positive axis parallel to the side (orthogonal to both n and the z axis)
    // v is the vector which is used for the port's local point's y coordinate and faces away from the board surface.
    Vec u = sidePositiveTangentialVector(port.side);
    Vec v = {0, 0, -1};

    // The base position of a port, if it has a local point of (0,0). This is the "origin" of the side.
    Vec base = {0, 0, partOuterHeight};
    if (port.side == North) { base.y = board.size[1]; }
    if (port.side == East)  { base.x = board.size[0]; }

    // The hole is a hull of translated cylinders, so the hole is a rounded shape with radius port.radius along port.path [If the radius is 0, we use a tiny cylinder with 4 faces]
    Component cyl = Cylinder(std::max(port.radius, .001), off_xy + 2 * eps, port.radius == 0 ? 4 : 32, false);
    cyl.translate(0, 0, -eps);

    // Added by: Anthony W. Rainer <*****@*****.**>
    if(port.side != Flat) {
	cyl.rotateEulerZXZ(0.0, -90.0, -90.0 * port.side);
    }else{
	cyl.rotateEulerZXZ(0.0, 180.0, 0);
    }

    // Add a cone for diagonal borders of the port hole
    double coneLength = off_xy - port.outset;
    Component cone = Cylinder(port.radius, port.radius + coneLength + 2 * eps, coneLength + 2 * eps, 32, false);
    cone.translate(0, 0, port.outset);

    // Added by: Anthony W. Rainer <*****@*****.**>
    if(port.side != Flat) {
	cone.rotateEulerZXZ(0.0, -90.0, -90.0 * port.side);
    }else{
	cone.rotateEulerZXZ(0.0, 180.0, 0);
    }

    // Build convex hull of translated copies of this cylinder along the path of the port
    CompositeComponent cylHull = Hull::create();
    CompositeComponent coneHull = Hull::create();
    for (auto localPoint : port.path)
    {
        Vec p;

	// Added by: Anthony W. Rainer <*****@*****.**>
	if(port.side != Flat) {
		p = base + localPoint.x*u + localPoint.y*v;
	} else {
		p.z = off_xy;
		p.x = localPoint.x;
		p.y = localPoint.y;
	}
        Component thisCyl = cyl.translatedCopy(p.x, p.y, p.z);
	cylHull.addComponent(thisCyl);

	Component thisCone = cone.translatedCopy(p.x, p.y, p.z);
	coneHull.addComponent(thisCone);
    }
    return component - (cylHull + coneHull);
}
CompositeComponent *CompositeComponent::clone() const{
    CompositeComponent* product = new CompositeComponent;
    for(size_t i = 0; i < this->size(); ++i){
        product->addComponent(std::shared_ptr<Component>(m_children[i]->clone()));
    }
    return product;
}
Example #3
0
Component CaseFactory::constructPart(Side whichSide)
{
    // Select parameters depending on which part to build
    auto innerHeight     = (whichSide == BottomSide) ? bottomInnerHeight()        : topInnerHeight();
    auto outerHeight     = (whichSide == BottomSide) ? bottomHeight()             : topHeight();
    auto forbiddenAreas  = (whichSide == BottomSide) ? board.bottomForbiddenAreas          : board.topForbiddenAreas;
    auto ports           = (whichSide == BottomSide) ? board.bottomPorts          : board.topPorts;
    auto wallSupports    = (whichSide == BottomSide) ? board.bottomWallSupports   : board.topWallSupports;
    auto extension       = (whichSide == outerExtensionOnSide) ? ExtensionOutside : ExtensionInside;
    auto screwHoleRadius =((whichSide == screwHeadsOnSide) ? holesAddRadiusLoose : holesAddRadiusTight) + board.holesRadius;
    auto screwHeads      = (whichSide == screwHeadsOnSide);

    // We start with the base
    Component c = constructBase(innerHeight, extension);

    // Add wall support
    for (auto wallSupport : wallSupports) {
        c = addWallSupport(c, outerHeight, wallSupport);
    }

    // Screw holes
    for (auto hole : board.holes) {
        c = addHoleForScrew(c, outerHeight, hole, screwHoleRadius, screwHeads);
    }

    // Added by: Anthony W. Rainer <*****@*****.**>
    // Modified by: Bogdan Vacaliuc <*****@*****.**> to allow selection of side
    if(whichSide == board.holeNutsSide) {
	// Screw holes Nuts
        for (auto holeNut : board.holeNuts) {
            c = addCavityForNut(c, outerHeight, board.holes[holeNut.holeIndex], holeNut);
        }
    }

    // Apply rounded corners (if enabled)
    if (cornerRadius > 0.0) {
        // Class "RoundedCube" of ooml is buggy as it doesn't respect the "faces" parameter.
        // So we construct our own rounded cuboid by taking the convex hull of eight spheres.
        Vec min = {-outset(), -outset(), 0};
        Vec max = outerDimensions() + min;
        Vec cornerOffset = {cornerRadius, cornerRadius, cornerRadius};
        min += cornerOffset;
        max -= cornerOffset;
        CompositeComponent roundedCorners = Hull::create();
        for (int corner = 0; corner < 8; corner++) {
            double x = (corner & (1 << 0)) ? min.x : max.x;
            double y = (corner & (1 << 1)) ? min.y : max.y;
            double z = (corner & (1 << 2)) ? min.z : max.z;
            roundedCorners.addComponent(Sphere(cornerRadius, cornerFaces).translatedCopy(x, y, z));
        }

        // Intersect the current part with the rounded cuboid
        c = c * roundedCorners;
    }

    // Port holes
    for (auto port : ports) {
        c = addHoleForPort(c, outerHeight, port);
    }

    // "Forbidden areas" of the board
    for (auto area : forbiddenAreas) {
        c = c - Cube(area.sx, area.sy, area.sz + extensionHeight() + eps, false)
                .translatedCopy(area.x, area.y, outerHeight - area.sz);
    }

    // If this is the top, we've just built it mirrored. So we mirror the y axis and move it so it matches the dimensions of the bottom part.
    if (whichSide == TopSide) {
        c.scale(1.0, -1.0, 1.0);
        c.translate(0.0, board.size[1], 0.0);
    }

    return c;
}