def mouseMoveEvent(self, event): if self._lastMousePos is not None: pos = [event.x(), event.y()] delta = [pos[0] - self._lastMousePos[0], pos[1] - self._lastMousePos[1]] result, eye = self._sceneviewer.getEyePosition() result, lookat = self._sceneviewer.getLookatPosition() result, up = self._sceneviewer.getUpVector() lookatToEye = vectorops.sub(eye, lookat) eyeDistance = vectorops.magnitude(lookatToEye) front = vectorops.div(lookatToEye, eyeDistance) right = vectorops.cross(up, front) if self._active_button == QtCore.Qt.LeftButton: mag = vectorops.magnitude(delta) prop = vectorops.div(delta, mag) axis = vectorops.add(vectorops.mult(up, prop[0]), vectorops.mult(right, prop[1])) angle = mag*0.002 self._model.rotateModel(axis, angle) elif self._active_button == QtCore.Qt.MiddleButton: result, l, r, b, t, near, far = self._sceneviewer.getViewingVolume() viewportWidth = self.width() viewportHeight = self.height() if viewportWidth > viewportHeight: eyeScale = (t - b) / viewportHeight else: eyeScale = (r - l) / viewportWidth offset = vectorops.add(vectorops.mult(right, eyeScale*delta[0]), vectorops.mult(up, -eyeScale*delta[1])) self._model.offsetModel(offset) elif self._active_button == QtCore.Qt.RightButton: factor = 1.0 + delta[1]*0.0005 if factor < 0.9: factor = 0.9 self._model.scaleModel(factor) self._lastMousePos = pos else: super(AlignmentSceneviewerWidget, self).mouseMoveEvent(event)
def get_curve_circle_points(x1, xd1, x2, xd2, r1, rd1, r2, rd2, xi, dmag, side, elementsCountAround): ''' :param dmag: Magnitude of derivative on curve. :param side: Vector in side direction of first node around. Need not be unit or exactly normal to curve at xi. :return: x[], d1[] around, d2[] along ''' cx = interpolateCubicHermite(x1, xd1, x2, xd2, xi) cxd = interpolateCubicHermiteDerivative(x1, xd1, x2, xd2, xi) mag_cxd = magnitude(cxd) cxd2 = interpolateCubicHermiteSecondDerivative(x1, xd1, x2, xd2, xi) mag_cxd2 = magnitude(cxd2) r = interpolateCubicHermite([ r1 ], [ rd1 ], [ r2 ], [ rd2 ], xi)[0] rd = interpolateCubicHermiteDerivative([ r1 ], [ rd1 ], [ r2 ], [ rd2 ], xi)[0] axis1 = normalize(cxd) axis3 = normalize(cross(axis1, side)) axis2 = cross(axis3, axis1) x, d1 = createCirclePoints(cx, mult(axis2, r), mult(axis3, r), elementsCountAround) curvatureVector = mult(cxd2, 1.0/(mag_cxd*mag_cxd)) d2 = [] radialGrowth = rd/(mag_cxd*r) for e in range(elementsCountAround): radialVector = sub(x[e], cx) dmagFinal = dmag*(1.0 - dot(radialVector, curvatureVector)) # add curvature and radius change components: d2.append(add(mult(cxd, dmagFinal/mag_cxd), mult(radialVector, dmagFinal*radialGrowth))) return x, d1, d2
def _stdViewsButtonClicked(self): sceneviewer = self._ui.sceneviewer_widget.getSceneviewer() if sceneviewer is not None: result, eyePosition, lookatPosition, upVector = sceneviewer.getLookatParameters( ) upVector = normalize(upVector) viewVector = sub(lookatPosition, eyePosition) viewDistance = magnitude(viewVector) viewVector = normalize(viewVector) viewX = dot(viewVector, [1.0, 0.0, 0.0]) viewY = dot(viewVector, [0.0, 1.0, 0.0]) viewZ = dot(viewVector, [0.0, 0.0, 1.0]) upX = dot(upVector, [1.0, 0.0, 0.0]) upY = dot(upVector, [0.0, 1.0, 0.0]) upZ = dot(upVector, [0.0, 0.0, 1.0]) if (viewZ < -0.999) and (upY > 0.999): # XY -> XZ viewVector = [0.0, 1.0, 0.0] upVector = [0.0, 0.0, 1.0] elif (viewY > 0.999) and (upZ > 0.999): # XZ -> YZ viewVector = [-1.0, 0.0, 0.0] upVector = [0.0, 0.0, 1.0] else: # XY viewVector = [0.0, 0.0, -1.0] upVector = [0.0, 1.0, 0.0] eyePosition = sub(lookatPosition, mult(viewVector, viewDistance)) sceneviewer.setLookatParametersNonSkew(eyePosition, lookatPosition, upVector)
def _imageButtonClicked(self): sceneviewer = self._ui.sceneviewer_widget.getSceneviewer() normal, up, offset = self._plane_model.getPlaneInfo() _, current_lookat_pos = sceneviewer.getLookatPosition() _, current_eye_pos = sceneviewer.getEyePosition() view_distance = vectorops.magnitude(vectorops.sub(current_eye_pos, current_lookat_pos)) eye_pos = vectorops.add(vectorops.mult(normal, view_distance), offset) lookat_pos = offset sceneviewer.setLookatParametersNonSkew(eye_pos, lookat_pos, up)
def mouseMoveEvent(self, event): if self._model.isStateAlign() and self._alignKeyPressed and ( self._lastMousePos is not None): pos = [event.x(), event.y()] delta = [ pos[0] - self._lastMousePos[0], pos[1] - self._lastMousePos[1] ] result, eye = self._sceneviewer.getEyePosition() result, lookat = self._sceneviewer.getLookatPosition() result, up = self._sceneviewer.getUpVector() lookatToEye = vectorops.sub(eye, lookat) eyeDistance = vectorops.magnitude(lookatToEye) front = vectorops.div(lookatToEye, eyeDistance) right = vectorops.cross(up, front) if self._active_button == QtCore.Qt.LeftButton: mag = vectorops.magnitude(delta) prop = vectorops.div(delta, mag) axis = vectorops.add(vectorops.mult(up, prop[0]), vectorops.mult(right, prop[1])) angle = mag * 0.002 self._model.rotateModel(axis, angle) elif self._active_button == QtCore.Qt.MiddleButton: result, l, r, b, t, near, far = self._sceneviewer.getViewingVolume( ) viewportWidth = self.width() viewportHeight = self.height() if viewportWidth > viewportHeight: eyeScale = (t - b) / viewportHeight else: eyeScale = (r - l) / viewportWidth offset = vectorops.add( vectorops.mult(right, eyeScale * delta[0]), vectorops.mult(up, -eyeScale * delta[1])) self._model.offsetModel(offset) elif self._active_button == QtCore.Qt.RightButton: factor = 1.0 + delta[1] * 0.0005 if factor < 0.9: factor = 0.9 self._model.scaleModel(factor) self._lastMousePos = pos else: super(AlignmentSceneviewerWidget, self).mouseMoveEvent(event)
def _updateAlignmentValues(self): fieldmodule = self._region.getFieldmodule() cache = fieldmodule.createFieldcache() _, t_matrix = self._scene.getTransformationMatrix() t_matrix = vectorops.reshape(t_matrix, (4, 4)) _, projection = self._stationary_projection_field.evaluateReal( cache, 16) projection = vectorops.reshape(projection, (4, 4)) projection = vectorops.matrixmult(t_matrix, projection) projection = vectorops.reshape(projection, -1) scale_vector = [ vectorops.magnitude([projection[0], projection[4], projection[8]]), vectorops.magnitude([projection[1], projection[5], projection[9]]), vectorops.magnitude([projection[2], projection[6], projection[10]]) ] rotation_matrix = [[projection[0], projection[1], projection[2]], [projection[4], projection[5], projection[6]], [projection[8], projection[9], projection[10]]] xScale = scale_vector[0] yScale = scale_vector[1] zScale = scale_vector[2] rot_mx = [[ projection[0] * xScale, projection[1] * yScale, projection[2] * zScale ], [ projection[4] * xScale, projection[5] * yScale, projection[6] * zScale ], [ projection[8] * xScale, projection[9] * yScale, projection[10] * zScale ]] euler_angles = vectorops.rotationMatrix3ToEuler(rotation_matrix) eul_anlges = vectorops.rotationMatrix3ToEuler(rot_mx) offset_vector = [projection[3], projection[7], projection[11]] settings = { 'euler_angles': eul_anlges, 'offset': offset_vector, 'scale': scale_vector } self.setAlignSettings(settings)
def _createNodeTree(self, generation, x1, d1, r, forkNormal): ''' Create node with specified x1, d1, r and recursively add two child nodes until generationCount. :param forkNormal: Unit direction normal to d1 and child branches. :return: Top node of tree. ''' node = TreeNode(x1, d1, r) if generation < self._generationCount: branchLength = magnitude(d1) * self._branchLengthRatio main = mult(d1, self._cosForkAngle * self._branchLengthRatio) side = mult(cross(forkNormal, d1), self._sinForkAngle * self._branchLengthRatio) branch1d1 = add(main, side) branch2d1 = sub(main, side) if self._branchArcRadians > 0.0: arcr = branchLength / self._branchArcRadians arc2 = mult(branch1d1, arcr / branchLength) arc1 = cross(arc2, forkNormal) arcc = sub(x1, arc1) branch1x2 = add( arcc, add(mult(arc1, self._cosBranchArc), mult(arc2, self._sinBranchArc))) branch1d2 = mult( add(mult(arc1, -self._sinBranchArc), mult(arc2, self._cosBranchArc)), branchLength / arcr) arc2 = mult(branch2d1, arcr / branchLength) arc1 = cross(forkNormal, arc2) arcc = sub(x1, arc1) branch2x2 = add( arcc, add(mult(arc1, self._cosBranchArc), mult(arc2, self._sinBranchArc))) branch2d2 = mult( add(mult(arc1, -self._sinBranchArc), mult(arc2, self._cosBranchArc)), branchLength / arcr) else: branch1x2 = add(x1, branch1d1) branch1d2 = branch1d1 branch2x2 = add(x1, branch2d1) branch2d2 = branch2d1 branch1Normal = normalize(cross(forkNormal, branch1d2)) branch2Normal = normalize(cross(forkNormal, branch2d2)) forkRadius = r * self._forkRadiusRatio node.addChild( self._createNodeTree(generation + 1, branch1x2, branch1d2, forkRadius * self._branchRadiusRatio, branch1Normal), branch1d1, forkRadius) node.addChild( self._createNodeTree(generation + 1, branch2x2, branch2d2, forkRadius * self._branchRadiusRatio, branch2Normal), branch2d1, forkRadius) return node
def smooth(self, updateDirections=False, maxIterations=10, arcLengthTolerance=1.0E-6): ''' :param maxIterations: Maximum iterations before stopping if not converging. :param arcLengthTolerance: Ratio of difference in arc length from last iteration divided by current arc length under which convergence is achieved. Required to be met by every element edge. ''' if not self._derivativeMap: return # no nodes being smoothed componentsCount = self._field.getNumberOfComponents() with ChangeManager(self._fieldmodule): fieldcache = self._fieldmodule.createFieldcache() for iter in range(maxIterations + 1): converged = True for edge in self._edgesMap.values(): lastArcLength = edge.getLastArcLength() arcLength = edge.evaluateArcLength(self._nodes, self._field, fieldcache) edge.updateLastArcLength() if (math.fabs(arcLength - lastArcLength)/arcLength) > arcLengthTolerance: converged = False if converged: print('Derivative smoothing: Converged after', iter, 'iterations.') break elif (iter == maxIterations): print('Derivative smoothing: Stopping after', maxIterations, 'iterations without converging.') break for derivativeKey, derivativeEdges in self._derivativeMap.items(): edgeCount = len(derivativeEdges) if edgeCount > 1: nodeIdentifier, nodeValueLabel, nodeVersion = derivativeKey fieldcache.setNode(self._nodes.findNodeByIdentifier(nodeIdentifier)) if updateDirections: x = [ 0.0 for _ in range(componentsCount) ] else: result, x = self._field.getNodeParameters(fieldcache, -1, nodeValueLabel, nodeVersion, componentsCount) mag = 0.0 for derivativeEdge in derivativeEdges: edge, expressionIndex, totalScaleFactor = derivativeEdge arcLength = edge.getArcLength() if updateDirections: delta = edge.getDelta() if totalScaleFactor < 0.0: delta = [ -d for d in delta ] for c in range(componentsCount): x[c] += delta[c] / arcLength if self._scalingMode == DerivativeScalingMode.ARITHMETIC_MEAN: mag += arcLength/math.fabs(totalScaleFactor) else: # self._scalingMode == DerivativeScalingMode.HARMONIC_MEAN mag += math.fabs(totalScaleFactor)/arcLength if self._scalingMode == DerivativeScalingMode.ARITHMETIC_MEAN: mag /= edgeCount else: # self._scalingMode == DerivativeScalingMode.HARMONIC_MEAN mag = edgeCount/mag if (mag <= 0.0): print('Node', nodeIdentifier, 'label', label, 'version', version, 'has negative mag', mag) x = setMagnitude(x, mag) result = self._field.setNodeParameters(fieldcache, -1, nodeValueLabel, nodeVersion, x) for derivativeKey, derivativeEdges in self._derivativeMap.items(): edgeCount = len(derivativeEdges) if edgeCount == 1: # boundary smoothing over single edge nodeIdentifier, nodeValueLabel, nodeVersion = derivativeKey edge, expressionIndex, totalScaleFactor = derivativeEdges[0] # re-evaluate arc length so parameters are up-to-date for other end arcLength = edge.evaluateArcLength(self._nodes, self._field, fieldcache) fieldcache.setNode(self._nodes.findNodeByIdentifier(nodeIdentifier)) # since changed by evaluateArcLength otherExpressionIndex = 3 if (expressionIndex == 1) else 1 otherd = edge.getParameter(otherExpressionIndex) if updateDirections: thisx = edge.getParameter(expressionIndex - 1) otherx = edge.getParameter(otherExpressionIndex - 1) bothEndsOnBoundary = False otherExpression = edge.getExpression(otherExpressionIndex) if len(otherExpression) == 1: otherNodeIdentifier, otherValueLabel, otherNodeVersion, otherTotalScaleFactor = otherExpression[0] otherDerivativeKey = (otherNodeIdentifier, otherValueLabel, otherNodeVersion) otherDerivativeEdges = self._derivativeMap.get(otherDerivativeKey) bothEndsOnBoundary = (otherDerivativeEdges is not None) and (len(otherDerivativeEdges) == 1) if bothEndsOnBoundary: if expressionIndex == 1: x = [ (otherx[c] - thisx[c]) for c in range(componentsCount) ] else: x = [ (thisx[c] - otherx[c]) for c in range(componentsCount) ] else: if expressionIndex == 1: x = interpolateLagrangeHermiteDerivative(thisx, otherx, otherd, 0.0) else: x = interpolateHermiteLagrangeDerivative(otherx, otherd, thisx, 1.0) x = [ d/totalScaleFactor for d in x ] else: result, x = self._field.getNodeParameters(fieldcache, -1, nodeValueLabel, nodeVersion, componentsCount) othermag = magnitude(otherd) mag = (2.0*arcLength - othermag)/math.fabs(totalScaleFactor) if (mag <= 0.0): print('Derivative smoothing: Node', nodeIdentifier, 'label', nodeValueLabel, 'version', nodeVersion, 'has negative magnitude', mag) x = setMagnitude(x, mag) result = self._field.setNodeParameters(fieldcache, -1, nodeValueLabel, nodeVersion, x) # record modified nodes while ChangeManager is in effect if self._editNodesetGroup: for derivativeKey in self._derivativeMap: self._editNodesetGroup.addNode((self._nodes.findNodeByIdentifier(derivativeKey[0]))) del fieldcache
def mouseMoveEvent(self, event): if self._editNode: mousePos = [event.x(), event.y()] nodeset = self._editNode.getNodeset() fieldmodule = nodeset.getFieldmodule() with ChangeManager(fieldmodule): meshEditsNodeset = self._model.getOrCreateMeshEditsNodesetGroup( nodeset) meshEditsNodeset.addNode(self._editNode) editCoordinateField = coordinateField = self._editGraphics.getCoordinateField( ) localScene = self._editGraphics.getScene( ) # need set local scene to get correct transformation if coordinateField.getCoordinateSystemType( ) != Field.COORDINATE_SYSTEM_TYPE_RECTANGULAR_CARTESIAN: editCoordinateField = fieldmodule.createFieldCoordinateTransformation( coordinateField) editCoordinateField.setCoordinateSystemType( Field.COORDINATE_SYSTEM_TYPE_RECTANGULAR_CARTESIAN) fieldcache = fieldmodule.createFieldcache() fieldcache.setNode(self._editNode) componentsCount = coordinateField.getNumberOfComponents() result, initialCoordinates = editCoordinateField.evaluateReal( fieldcache, componentsCount) if result == RESULT_OK: for c in range(componentsCount, 3): initialCoordinates.append(0.0) pointattr = self._editGraphics.getGraphicspointattributes() editVectorField = vectorField = pointattr.getOrientationScaleField( ) pointBaseSize = pointattr.getBaseSize(3)[1][0] pointScaleFactor = pointattr.getScaleFactors(3)[1][0] if editVectorField.isValid() and (vectorField.getNumberOfComponents() == componentsCount) \ and (pointBaseSize == 0.0) and (pointScaleFactor != 0.0): if vectorField.getCoordinateSystemType( ) != Field.COORDINATE_SYSTEM_TYPE_RECTANGULAR_CARTESIAN: editVectorField = fieldmodule.createFieldCoordinateTransformation( vectorField, coordinateField) editVectorField.setCoordinateSystemType( Field. COORDINATE_SYSTEM_TYPE_RECTANGULAR_CARTESIAN) result, initialVector = editVectorField.evaluateReal( fieldcache, componentsCount) for c in range(componentsCount, 3): initialVector.append(0.0) initialTipCoordinates = [ (initialCoordinates[c] + initialVector[c] * pointScaleFactor) for c in range(3) ] windowCoordinates = self.projectLocal( initialTipCoordinates[0], initialTipCoordinates[1], initialTipCoordinates[2], localScene) finalTipCoordinates = self.unprojectLocal( mousePos[0], -mousePos[1], windowCoordinates[2], localScene) finalVector = [ (finalTipCoordinates[c] - initialCoordinates[c]) / pointScaleFactor for c in range(3) ] result = editVectorField.assignReal( fieldcache, finalVector) else: windowCoordinates = self.projectLocal( initialCoordinates[0], initialCoordinates[1], initialCoordinates[2], localScene) xa = self.unprojectLocal(self._lastMousePos[0], -self._lastMousePos[1], windowCoordinates[2], localScene) xb = self.unprojectLocal(mousePos[0], -mousePos[1], windowCoordinates[2], localScene) finalCoordinates = [ (initialCoordinates[c] + xb[c] - xa[c]) for c in range(3) ] result = editCoordinateField.assignReal( fieldcache, finalCoordinates) del editVectorField del editCoordinateField del fieldcache self._lastMousePos = mousePos event.accept() return if self._alignMode != self.AlignMode.NONE: mousePos = [event.x(), event.y()] delta = [ mousePos[0] - self._lastMousePos[0], mousePos[1] - self._lastMousePos[1] ] result, eye = self._sceneviewer.getEyePosition() result, lookat = self._sceneviewer.getLookatPosition() result, up = self._sceneviewer.getUpVector() lookatToEye = sub(eye, lookat) eyeDistance = magnitude(lookatToEye) front = div(lookatToEye, eyeDistance) right = cross(up, front) if self._alignMode == self.AlignMode.ROTATION: mag = magnitude(delta) prop = div(delta, mag) axis = add(mult(up, prop[0]), mult(right, prop[1])) angle = mag * 0.002 #print('delta', delta, 'axis', axis, 'angle', angle) self._model.interactionRotate(axis, angle) elif self._alignMode == self.AlignMode.SCALE: factor = 1.0 + delta[1] * 0.0005 if factor < 0.9: factor = 0.9 self._model.interactionScale(factor) elif self._alignMode == self.AlignMode.TRANSLATION: result, l, r, b, t, near, far = self._sceneviewer.getViewingVolume( ) viewportWidth = self.width() viewportHeight = self.height() if viewportWidth > viewportHeight: eyeScale = (t - b) / viewportHeight else: eyeScale = (r - l) / viewportWidth offset = add(mult(right, eyeScale * delta[0]), mult(up, -eyeScale * delta[1])) self._model.interactionTranslate(offset) self._lastMousePos = mousePos event.accept() return else: super(NodeEditorSceneviewerWidget, self).mouseMoveEvent(event)
def test_transformation(self): """ Test transformation of a box scaffold with scaffold package. """ scaffoldPackage = ScaffoldPackage(MeshType_3d_box1) tmpScale = scaffoldPackage.getScale() TOL = 1.0E-7 FINETOL = 1.0E-12 assertAlmostEqualList(self, tmpScale, [1.0, 1.0, 1.0], delta=FINETOL) newScale = [2.0, 1.5, 0.5] scaffoldPackage.setScale(newScale) tmpScale = scaffoldPackage.getScale() assertAlmostEqualList(self, tmpScale, newScale, delta=FINETOL) tmpRotation = scaffoldPackage.getRotation() assertAlmostEqualList(self, tmpRotation, [0.0, 0.0, 0.0], delta=FINETOL) newRotation = [30.0, -10.0, 90.0] scaffoldPackage.setRotation(newRotation) tmpRotation = scaffoldPackage.getRotation() assertAlmostEqualList(self, tmpRotation, newRotation, delta=FINETOL) tmpTranslation = scaffoldPackage.getTranslation() assertAlmostEqualList(self, tmpTranslation, [0.0, 0.0, 0.0], delta=FINETOL) newTranslation = [0.5, 1.2, -0.1] scaffoldPackage.setTranslation(newTranslation) tmpTranslation = scaffoldPackage.getTranslation() assertAlmostEqualList(self, tmpTranslation, newTranslation, delta=FINETOL) context = Context("Test") region = context.getDefaultRegion() self.assertTrue(region.isValid()) scaffoldPackage.generate(region) fieldmodule = region.getFieldmodule() nodes = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) self.assertEqual(8, nodes.getSize()) coordinates = fieldmodule.findFieldByName( "coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) assertAlmostEqualList(self, minimums, [ 2.744244002293470e-01, 6.367511648575830e-01, -1.000000000000000e-01 ], delta=TOL) assertAlmostEqualList(self, maximums, [ 2.455737063904887e+00, 2.184807753012208e+00, 1.724507984852172e+00 ], delta=TOL) node = nodes.findNodeByIdentifier(8) self.assertTrue(node.isValid()) fieldcache = fieldmodule.createFieldcache() fieldcache.setNode(node) result, x = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_VALUE, 1, 3) self.assertEqual(RESULT_OK, result) assertAlmostEqualList(self, x, [ 2.230161464134234e+00, 1.621558917869791e+00, 1.724507984852172e+00 ], delta=TOL) # derivative magnitudes must also equal scale result, d1 = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS1, 1, 3) self.assertEqual(RESULT_OK, result) assertAlmostEqualList(self, d1, [ 1.705737064039425e+00, 9.848077530127952e-01, 3.472963553408093e-01 ], delta=TOL) self.assertAlmostEqual(newScale[0], magnitude(d1), delta=TOL) result, d2 = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS2, 1, 3) self.assertEqual(RESULT_OK, result) assertAlmostEqualList(self, d2, [ -2.255755995328457e-01, -1.302361332111701e-01, 1.477211629352659e+00 ], delta=TOL) self.assertAlmostEqual(newScale[1], magnitude(d2), delta=TOL) result, d3 = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS3, 1, 3) self.assertEqual(RESULT_OK, result) assertAlmostEqualList(self, d3, [ 2.499999998128999e-01, -4.330127019169794e-01, 0.000000000000000e+00 ], delta=TOL) self.assertAlmostEqual(newScale[2], magnitude(d3), delta=TOL)
def _get_auto_point_size(self): minimums, maximums = self._get_data_range() data_size = maths.magnitude(maths.sub(maximums, minimums)) return 0.25 * data_size