// Inherited Methods void PhysXMeshCollider::scale(const glm::vec3 &scaling) { for (physx::PxShape *shape : getShapes()) { const physx::PxVec3 realScaling(scaling.x, scaling.y, scaling.z); physx::PxTransform localPose = shape->getLocalPose(); const physx::PxMat33 scalingMatrix = physx::PxMat33::createDiagonal(realScaling) * physx::PxMat33(localPose.q); if (isConvex()) { physx::PxConvexMeshGeometry &convexMesh = shape->getGeometry().convexMesh(); convexMesh.scale.scale.x *= scalingMatrix.column0.magnitude(); convexMesh.scale.scale.y *= scalingMatrix.column1.magnitude(); convexMesh.scale.scale.z *= scalingMatrix.column2.magnitude(); shape->setGeometry(convexMesh); } else { physx::PxTriangleMeshGeometry &triangleMesh = shape->getGeometry().triangleMesh(); triangleMesh.scale.scale.x *= scalingMatrix.column0.magnitude(); triangleMesh.scale.scale.y *= scalingMatrix.column1.magnitude(); triangleMesh.scale.scale.z *= scalingMatrix.column2.magnitude(); shape->setGeometry(triangleMesh); } localPose.p = localPose.p.multiply(realScaling); shape->setLocalPose(localPose); } }
/** * \return Points on entity which are intersection points with the * given other entity. If \c same is true, the two datas originate * from the same entity. */ QList<RVector> REntityData::getIntersectionPoints( const REntityData& other, bool limited, bool same, const RBox& queryBox, bool ignoreComplex) const { QList<RVector> ret; QList<QSharedPointer<RShape> > shapes1 = getShapes(queryBox, ignoreComplex, true); if (RMouseEvent::hasMouseMoved()) { return QList<RVector>(); } QList<QSharedPointer<RShape> > shapes2 = other.getShapes(queryBox, ignoreComplex, true); for (int i=0; i<shapes1.size(); i++) { for (int k=0; k<shapes2.size(); k++) { if (RMouseEvent::hasMouseMoved()) { return QList<RVector>(); } // if (same) { // if (abs(i-k)<=1) { // // same or connecting segment of same entity // continue; // } // } ret.append( shapes1.at(i)->getIntersectionPoints(*shapes2.at(k), limited, same) ); } } return ret; }
void MapTool:: selectShape(const Geometry::Point<double,3>& pos) { MapManager* mapMan = crusta->getMapManager(); Shape*& curShape = mapMan->getActiveShape(toolId); Shape* oldShape = curShape; ShapePtrs shapes = getShapes(); double threshold = 1.0 / Vrui::getNavigationTransformation().getScaling(); threshold *= mapMan->getSelectDistance(); bool noShapeSelected = true; for (ShapePtrs::iterator it=shapes.begin(); it!=shapes.end(); ++it) { double distance; Shape::ControlId control = (*it)->select(pos, distance); if (control!=Shape::BAD_ID && distance<=threshold) { curShape = *it; threshold = distance; noShapeSelected = false; } } if (noShapeSelected && curShape!=NULL) unselectShape(curShape, curControl); //inform the manager that the active shape has changed if (curShape != oldShape) mapMan->updateActiveShape(toolId); }
void RDimDiametricData::updateTextData() const { initTextData(); double dimgap = getDimgap(); if (RMath::isNaN(defaultAngle)) { // updates default angle: getShapes(); } // move text to the side if appropriate: if (!hasCustomTextPosition()) { //RBox bbox = textData.getBoundingBox(); if (!RMath::isNaN(dimLineLength) && textData.getWidth()>dimLineLength) { RVector distH; distH.setPolar(textData.getWidth()/2.0 +dimLineLength/2.0+dimgap, defaultAngle); textPositionSide = textPositionCenter; textPositionSide+=distH; } else { textPositionSide = RVector::invalid; } } textData.rotate(defaultAngle, RVector(0,0)); textData.move(getTextPosition()); }
/** * \return The one shape that is part of this entity which is the * closest to the given position. */ QSharedPointer<RShape> REntityData::getClosestShape(const RVector& pos, double range) const { QSharedPointer<RShape> ret; QList<QSharedPointer<RShape> > shapes; if (RMath::isNaN(range)) { shapes = getShapes(); } else { shapes = getShapes(RBox(pos, range)); } // entity not based on shape: if (shapes.size()==0) { return ret; } // entity based on one or more shapes, find closest: double minDistance = RMAXDOUBLE; QList<QSharedPointer<RShape> >::const_iterator it; for (it=shapes.constBegin(); it!=shapes.constEnd(); ++it) { QSharedPointer<RShape> shape = (*it); // explode shape if possible: QList<QSharedPointer<RShape> > subShapes; QSharedPointer<RExplodable> explodable = shape.dynamicCast<RExplodable>(); // 20110916: interpolated shapes are not exploded at this point (e.g. // for perpendicular snap to spline inside block): if (explodable.isNull() || shape->isInterpolated()) { subShapes.append(QSharedPointer<RShape>(shape->clone())); } else { subShapes = explodable->getExploded(); } QList<QSharedPointer<RShape> >::iterator it2; for (it2=subShapes.begin(); it2!=subShapes.end(); ++it2) { QSharedPointer<RShape> shape2 = (*it2); double distance = shape2->getDistanceTo(pos); if (distance<minDistance) { minDistance = distance; ret = shape2; } } } return ret; }
/** * \return Vector of center points of this entity. Used for snap to * center points. */ QList<RVector> REntityData::getCenterPoints(const RBox& queryBox) const { QList<RVector> ret; QList<QSharedPointer<RShape> > shapes = getShapes(queryBox); for (int i=0; i<shapes.size(); i++) { ret.append(shapes.at(i)->getCenterPoints()); } return ret; }
/** * \return Points on entity which are intersection points with the * given shape. */ QList<RVector> REntityData::getIntersectionPoints(const RShape& shape, bool limited, const RBox& queryBox) const { QList<RVector> ret; QList<QSharedPointer<RShape> > shapes1 = getShapes(queryBox); for (int i=0; i<shapes1.size(); i++) { ret.append(shapes1.at(i)->getIntersectionPoints(shape, limited)); } return ret; }
void PhysXMeshCollider::updateShape(void) { static_cast<PhysXCollider *>(this)->updateShape(static_cast<PhysXWorld *>(getWorld())->getCollisionShapes(getMesh(), isConvex())); for (physx::PxShape *shape : getShapes()) { shape->setMaterials(&static_cast<PhysXMaterial *>(getMaterial())->material, 1); } }
/** * \return Points on entity with given \c distance to either endpoint. * Used for snap to points with distance on entity. */ QList<RVector> REntityData::getPointsWithDistanceToEnd(double distance, RS::From from, const RBox& queryBox) const { QList<RVector> ret; QList<QSharedPointer<RShape> > shapes = getShapes(queryBox); for (int i=0; i<shapes.size(); i++) { ret.append(shapes.at(i)->getPointsWithDistanceToEnd(distance, from)); } return ret; }
// Constructors PhysXMeshCollider::PhysXMeshCollider(WorldInterface *world, const std::string &mesh, Private::GenericData *data) : ColliderInterface(world, data), MeshColliderInterface(world, mesh, IsConvexByDefault(), data), PhysXCollider(world, data, static_cast<PhysXWorld *>(world)->getCollisionShapes(mesh, isConvex())) { for (physx::PxShape *shape : getShapes()) { shape->setMaterials(&static_cast<PhysXMaterial *>(getMaterial())->material, 1); } }
/** * \return True if the given point is on this entity. */ bool REntityData::isOnEntity(const RVector& point, bool limited) const { QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { if (shapes.at(i)->isOnShape(point, limited)) { return true; } } return false; }
void RDimensionData::updateTextData() const { initTextData(); if (RMath::isNaN(defaultAngle)) { // updates default angle: getShapes(); } textData.rotate(defaultAngle, RVector(0,0)); textData.move(getTextPosition()); }
/** * \return The bounding box that contains this entity. */ RBox REntityData::getBoundingBox(bool ignoreEmpty) const { Q_UNUSED(ignoreEmpty) RBox ret; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { RBox bb = shapes.at(i)->getBoundingBox(); ret.growToInclude(bb); } return ret; }
/** * \return The distance vector from this entity to the given point. * * \param point the point to which the distance was measured * * \param limited: If true, an invalid vector is returned if the * closest point on the entity is outside of the entity (e.g. in * the extension line of a line or outside the start / end angle * of an arc). */ RVector REntityData::getVectorTo(const RVector& point, bool limited) const { RVector ret = RVector::invalid; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { shapes.at(i)->to2D(); RVector r = shapes.at(i)->getVectorTo(point, limited); if (!ret.isValid() || r.getMagnitude()<ret.getMagnitude()) { ret = r; } } return ret; }
/** * \return True if this entity intersects with the given shape, * false otherwise. * \todo better to pass another entity data object? */ bool REntityData::intersectsWith(const RShape& shape) const { QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { if (shapes.at(i)==NULL) { qWarning() << "REntityData::intersectsWith: ignoring NULL shape"; continue; } if (shapes.at(i)->intersectsWith(shape)) { return true; } } return false; }
/** * \return The bounding box that contains this entity. */ RBox REntityData::getBoundingBox() const { RBox bb; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { if (!bb.isValid()) { bb = shapes.at(i)->getBoundingBox(); } else { bb.growToInclude(shapes.at(i)->getBoundingBox()); } } return bb; }
void RDimLinearData::updateTextData() const { initTextData(); double dimgap = getDimgap(); if (RMath::isNaN(defaultAngle)) { // updates default angle: getShapes(); } // move text to the side if appropriate: if (!hasCustomTextPosition()) { // RVector newTextPos = dimensionLine.getMiddlePoint(); // RVector distV; // // rotate text so it's readable from the bottom or right (ISO) // // quadrant 1 & 4 // if (corrected) { // distV.setPolar(dimgap + dimtxt/2.0, dimAngle1-M_PI/2.0); // } else { // distV.setPolar(dimgap + dimtxt/2.0, dimAngle1+M_PI/2.0); // } // // move text away from dimension line: // newTextPos+=distV; // // TODO: resets textPosition if text was moved to the side for lack of space: // textPosition = newTextPos; // qDebug() << "RDimensionData::getDimensionLineShapes(): 1: textPosition: " << textPosition; // //updateTextData(); // qDebug() << "RDimensionData::getDimensionLineShapes(): 2: textPosition: " << textPosition; if (!RMath::isNaN(dimLineLength) && textData.getWidth()>dimLineLength) { RVector distH; distH.setPolar(textData.getWidth()/2.0+dimLineLength/2.0+dimgap, defaultAngle); textPositionSide = textPositionCenter; textPositionSide+=distH; //qDebug() << "RDimLinearData::updateTextData(): textPosition (side): " << textPositionCenter; } else { textPositionSide = RVector::invalid; } } textData.rotate(defaultAngle, RVector(0,0)); textData.move(getTextPosition()); }
/** * \return Points on entity which are intersection points with the * given other entity. If \c same is true, the two datas originate * from the same entity. */ QList<RVector> REntityData::getIntersectionPoints( const REntityData& other, bool limited, bool same, const RBox& queryBox) const { QList<RVector> ret; QList<QSharedPointer<RShape> > shapes1 = getShapes(queryBox); QList<QSharedPointer<RShape> > shapes2 = other.getShapes(queryBox); for (int i=0; i<shapes1.size(); i++) { for (int k=0; k<shapes2.size(); k++) { ret.append( shapes1.at(i)->getIntersectionPoints(*shapes2.at(k), limited, same) ); } } return ret; }
/** * \return Closest point to \c point on this entity. Used for snap to * points on entity. */ RVector REntityData::getClosestPointOnEntity(const RVector& point, double range, bool limited) const { Q_UNUSED(range) RVector ret = RVector::invalid; double minDist = RMAXDOUBLE; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { RVector r = shapes.at(i)->getClosestPointOnShape(point, limited); double dist = r.getDistanceTo(point); if (!ret.isValid() || dist<minDist) { ret = r; minDist = dist; } } return ret; }
/** * \return Points on entity which are intersection points with the * given other entity. If \c same is true, the two datas originate * from the same entity. */ QList<RVector> RPolylineData::getIntersectionPoints( const REntityData& other, bool limited, bool same, const RBox& queryBox, bool ignoreComplex) const { Q_UNUSED(ignoreComplex) QList<RVector> ret; QList<QSharedPointer<RShape> > shapes1 = getShapes(queryBox, true); //getExploded(); QList<QSharedPointer<RShape> > shapes2; if (same) { shapes2 = shapes1; } else { const RPolylineData* otherPl = dynamic_cast<const RPolylineData*>(&other); if (otherPl!=NULL) { //shapes2All = otherPl->getExploded(); shapes2 = other.getShapes(queryBox, true); } else { shapes2 = other.getShapes(queryBox); } } for (int i1=0; i1<shapes1.size(); i1++) { int i2Start = 0; if (same) { i2Start = i1+1; } for (int i2=i2Start; i2<shapes2.size(); i2++) { // very same polyline segments can't intersect: if (same && i1==i2) { continue; } QSharedPointer<RShape> shape1 = shapes1.at(i1); QSharedPointer<RShape> shape2 = shapes2.at(i2); QList<RVector> candidates = shape1->getIntersectionPoints(*shape2, limited, false); if (same) { // polyline internal intersections: if (shape1->isDirected() && shape2->isDirected()) { // ignore polyline nodes: for (int c=0; c<candidates.size(); c++) { if (candidates[c].equalsFuzzy(shape1->getStartPoint())) { continue; } if (candidates[c].equalsFuzzy(shape1->getEndPoint())) { continue; } if (candidates[c].equalsFuzzy(shape2->getStartPoint())) { continue; } if (candidates[c].equalsFuzzy(shape2->getEndPoint())) { continue; } ret.append(candidates[c]); } } } else { ret.append(candidates); } } } return ret; }
/** * @brief Returns cell radius. * * @note Only for cells with circle shape. * * @return */ units::Length getRadius() const { return getShapes()[0].getCircle().radius; }