Example #1
0
    def orbit(self, ref, axis, amt):
        """
        Orbit the camera around an axis passing through a reerence point ref -
        this one orbits relative to the camera axes
        Currently, this function has the undesirable side-effect of possibly
        breaking the "camera.yz is parallel to the world Y=0 plane" constraint,
        and should not be used unless you know what you're doing.
        """
        # Counter-rotate the camera.
        self.rotate(axis=axis, amt=amt)

        # Find the vector from the reference point to the camera
        vec = diff3D(ref, self.pos)
        # Rotate this vector around the axis
        if axis == X_AXIS:
            vec = rotate3D(vec, self.yz, amt)
        elif axis == Y_AXIS:
            vec = rotate3D(vec, self.up, amt)
        elif axis == Z_AXIS:
            vec = rotate3D(vec, self.vpn, -1 * amt)

        # Cacheable: Handled by setattr hook

        # Convert the vector into worldspace coordinates
        self.pos = add3D(ref, vec)
Example #2
0
 def makeStepVal(name, start, end, steps, locks=self._moveLock):
     """
     This function gets called in event time, not right now!
     """
     if name in locks:
         # Special case
         # We set =end on every frame if the end is a function (lambda).
         return None
     elif isinstance(end, (tuple, list)):
         # Assume these are 3D values.
         return div3D(
             diff3D(start, end),
             steps
         )
     elif isinstance(end, FunctionType):
         # Evaluate lambdas here:
         # in clocktime this is the start of movement.
         # This can only lead to confusion.
         print "self:", self
         print "kwargs:", kwargs
         print "name:", name
         print "end:", end
         assert (False)
     else:
         return float(end - start) / steps
Example #3
0
    def absorbit(self, ref, axis, amt):
        """
        Orbit the camera around an axis passing through a reference
        point ref.
        """
        # Position the reference point in the proper plane with the camera
        # position.
        ref = ref[:axis] + (self.pos[axis],) + ref[axis + 1:]
        # Counter-rotate the camera.
        self.absrotate(axis=axis, amt=-1 * amt)

        delta = diff3D(ref, self.pos)
        r = dist3D(c=delta)

        # Cacheable: All these handled by setattr hook

        if axis == X_AXIS:
            theta = atan2(delta[Y_AXIS], delta[Z_AXIS])
            theta = theta + (self.rotateSpeed * amt * pi / 180)
            self.pos = add3D(ref, (0, r * sin(theta), r * cos(theta)))
        elif axis == Y_AXIS:
            theta = atan2(delta[Z_AXIS], delta[X_AXIS])
            theta = theta + (self.rotateSpeed * amt * pi / 180)
            self.pos = add3D(ref, (r * cos(theta), 0, r * sin(theta)))
        elif axis == Z_AXIS:
            theta = atan2(delta[X_AXIS], delta[Y_AXIS])
            theta = theta + (-1 * self.rotateSpeed * amt * pi / 180)
            self.pos = add3D(ref, (r * sin(theta), r * cos(theta), 0))
Example #4
0
    def drawEdgeSelection(self, edge, alpha=0.4):
        """Draw a hilight around the edge."""
        if isinstance(edge, SuperEdge):
            for subedge in edge.edgeOrder():
                self.drawEdgeSelection(subedge)
            for vx in edge.bends:
                self.drawVertexSelection(vx)
            return

        ctx = self.graph.parent
        # Multiply points if snapping to grid
        # for Netcli (has no parent)
        showG = False
        if not ctx == None:
            if ctx.showGrid:
                showG = True
        if showG:
            srcpos = utilities.mult3D(edge.source.pos, ctx.spacing)
            tgtpos = utilities.mult3D(edge.target.pos, ctx.spacing)
        else:
            srcpos = edge.source.pos
            tgtpos = edge.target.pos

        diff = utilities.diff3D(srcpos, tgtpos)
        dist = utilities.dist3D(c=diff)

        # Avoid dividing by zero -
        # don't draw anything for zero-length edges
        if dist <= 0:
            return

        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        glPushMatrix()

        pigment = edge.color + (alpha,)
        glColor4f(*pigment)

        # Figure out radius boost factor
        x = max(log(40 * edge.radius, 10), 0)

        phi = acos(diff[Z_AXIS] / dist) * 180 / pi
        theta = atan2(diff[Y_AXIS], diff[X_AXIS]) * 180 / pi
        glTranslatef(*srcpos)
        glRotatef(theta, 0.0, 0.0, 1.0)
        glRotatef(phi, 0.0, 1.0, 0.0)
        gluQuadricOrientation(self.quad, GLU_OUTSIDE)
        gluQuadricTexture(self.quad, GL_TRUE)
        gluQuadricDrawStyle(self.quad, GLU_FILL)
        gluQuadricNormals(self.quad, GLU_SMOOTH)
        # glRotated(90, 1, 0, 0)
        gluCylinder(self.quad, edge.radius + x, edge.radius + x, dist, config.current['global:draw-edge-sides'],
                    config.current['global:draw-edge-sides'])

        glPopMatrix()
        glDisable(GL_BLEND)
Example #5
0
    def arrangeStepwise(self, graph, vertices, newPos, duration, wait=0.0, tween=True):
        """
        Arrange the vertices of the graph into a new layout
        specified by an indexed list of new positions newPos.
        The vertices will be positioned one at a time.
        """
        assert (len(newPos) == len(vertices))
        delay = float(duration) / len(vertices)

        from math import floor

        if tween:
            if delay > (1.0 / self.parent.fps):
                # No sense tweening faster than the frame rate can keep up
                stepsPerVert = int(floor(delay / (1.0 / self.parent.fps)))
                totalMove = [diff3D(a, b) for a, b in zip([x.pos for x in vertices], newPos)]
                partialMove = [div3D(x, stepsPerVert) for x in totalMove]
            else:
                tween = False

        accum = wait

        for i in range(len(vertices)):
            if tween:
                accum += delay / stepsPerVert
                for step in range(stepsPerVert - 1):
                    self.post(accum,
                              objects=(
                              vertices[i],
                              ),
                              props=(
                              (
                              'pos',
                              add3D(vertices[i].pos, mult3D(partialMove[i], (step + 1))),
                              ),
                              ),
                              changeGraph=graph,
                    )
                    accum += delay / stepsPerVert
            else:
                accum += delay
            self.post(accum,
                      objects=(
                      vertices[i],
                      ),
                      props=(
                      ('pos', newPos[i]),
                      ),
                      changeGraph=graph,
            )

        self.signal()
Example #6
0
    def __init__(self, ctx, vertex, snap, relative=False, updateHUD=None):
        Drawable.__init__(self)
        self.ctx = ctx
        self.vertex = vertex
        self.snap = snap
        self.relative = relative
        self.updateHUD = updateHUD

        if self.relative:
            startpos = self.vertex.pos
            startpoint = self.ctx.cursor.realPosition(self.ctx.camera)

            from utilities import diff3D

            self.offset = diff3D(startpoint, startpos)
Example #7
0
    def InputPos(self, pos):
        """
        Translate an input device position for the cursor.
        """
        from utilities import add3D, diff3D, mult3D

        self.move = False
        #Initialize jitter last position
        if self.first:
            self.lastPos = self.posMap(*pos)
            self.first = False

        if self.calibrate:
            mapped = self.posMap(*pos)
            offset = mult3D(mapped, self.posScale)
            self.posOrigin = offset
            self.calibrate = False

        if not self.manager.contexts.active:
            return

        # Translate the cursor position for use
        mapped = self.posMap(*pos)
        #Check for jitter
        for i in range(0, 3):
            dif = abs(mapped[i] - self.lastPos[i])
            if dif < float(self.jitter):
                self.move = False or self.move
            else:
                self.move = True
        #Real Movement - not jitter!
        if self.move:
            offset = mult3D(mapped, self.posScale)
            offset = diff3D(self.posOrigin, offset)
            self.manager.contexts.active.cursor.inputPos(offset)
        self.manager.contexts.active.showCursor = True
        self.lastPos = mapped

        # Determine if cursor is below ground plane
        oldStatus = self.manager.contexts.active.HUDstatus
        if self.manager.contexts.active.graph.findGroundPlane() > \
                self.manager.contexts.active.cursor.realPosition( \
                        self.manager.contexts.active.camera)[1]:
            self.manager.contexts.active.HUDstatus = "Cursor below groundplane"
        else:
            if oldStatus == "Cursor below groundplane":
                oldStatus = ""
            self.manager.contexts.active.HUDstatus = oldStatus
Example #8
0
    def perspCameraLookatMove(self, camera, newPos, fixLook, duration, wait=0.0):
        """
        Moves the camera smoothly to a new position and orientation.
        If newLook is None, does not change the orientation of the camera.
        If newPos is None, does not change the position of the camera.
        """
        from camera import Camera, OrthoCamera, X_AXIS, Y_AXIS, Z_AXIS

        assert (not isinstance(camera, OrthoCamera))

        fixLook = self.normalizePos(fixLook)
        steps = int(duration * self.parent.fps)

        deltaPos = diff3D(camera.pos, newPos)
        stepPos = div3D(deltaPos, steps)

        accum = wait
        delay = 1.0 / self.parent.fps

        # Set up the animation
        for i in range(steps - 1):
            accum += delay

            self.post(accum,
                      objects=(camera,),
                      props=(
                      ( 'pos', add3D(camera.pos, mult3D(stepPos, i + 1)) ),
                      ( 'lookAt', fixLook),
                      ),
                      call=(
                      ('absrotate', (Y_AXIS, stepYaw), {}),
                      ('rotate', (X_AXIS, stepPitch), {}),
                      ),
            )

        # Finish up in the correct place
        accum += delay
        self.post(accum,
                  objects=(camera,),
                  props=(
                  ('pos', newPos),
                  ('lookAt', fixLook),
                  ),
        )

        self.signal()
Example #9
0
    def arrangeMorph(self, graph, vertices, newPos, duration, wait=0.0):
        """
        Arrange the vertices of the graph into a new layout
        specified by an indexed list of new positions newPos.
        The vertices will be positioned simultaneously (smooth morph)
        """
        assert (len(newPos) == len(vertices))

        accum = wait

        steps = int(duration * self.parent.fps)
        delay = 1.0 / self.parent.fps

        d = [div3D(diff3D(a.pos, b), steps) for a, b in zip(vertices, newPos)]

        for i in range(steps - 1):
            accum += delay
            self.post(accum,
                      objects=vertices,
                      multiprops=(
                      (
                      'pos',
                      [add3D(a.pos, mult3D(b, i + 1)) for a, b in zip(vertices, d)]
                      ),
                      ),
                      changeGraph=graph,
            )

        accum += delay
        self.post(accum,
                  objects=vertices,
                  multiprops=(
                  ('pos', newPos),
                  ),
                  changeGraph=graph,
        )
        self.signal()
Example #10
0
    def InputPos(self, pos):
        """
        Translate an input device position for the cursor.
        """
        from utilities import add3D, diff3D, mult3D
        #Camera jitter: no move to start
        self.move = False
        #Initiate jitter last position
        if self.first:
            self.lastPos = self.posMap(*pos)
            self.first = False
            print "jitter:", self.jitter
        if self.calibrate:
            mapped = self.posMap(*pos)
            offset = mult3D(mapped, self.posScale)
            self.posOrigin = offset
            self.calibrate = False

        if not self.manager.contexts.active:
            return

        # Translate the cursor position for use
        mapped = self.posMap(*pos)
        #Check for jitter
        for i in range(0, 3):
            dif = abs(mapped[i] - self.lastPos[i])
            if dif < float(self.jitter):
                self.move = False or self.move
            else:
                self.move = True
        #Real Movement - not jitter!
        if self.move:
            offset = mult3D(mapped, self.posScale)
            offset = diff3D(self.posOrigin, offset)
            self.manager.contexts.active.camera.inputTrackPos(offset)
        self.lastPos = mapped
Example #11
0
    def drawHUD(self, camera, vertices, pos=None, status=''):
        from OpenGL.GLUT import glutStrokeCharacter, GLUT_STROKE_MONO_ROMAN

        view = glGetInteger(GL_VIEWPORT)
        if (view[1] != 0) or (view[3] != 0):
            # print "view = [", view[0], ",", view[1], ",", view[2], ",", view[3]
            # Switch to an orthogonal projection for drawing the HUD
            glDisable(GL_LIGHTING)
            glDisable(GL_DEPTH_TEST)
            glMatrixMode(GL_PROJECTION)
            glPushMatrix()
            glLoadIdentity()
            vheight = view[3] - view[1]
            vwidth = view[2]
            right = 100.0
            top = float(vheight) / float(vwidth) * right
            glOrtho(0.0, right, 0.0, top, 0.0, 1.0)
            glMatrixMode(GL_MODELVIEW)
            glPushMatrix()
            glLoadIdentity()
            gluLookAt(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
            #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glEnable(GL_BLEND)
            glEnable(GL_LINE_SMOOTH)
            glEnable(GL_POLYGON_SMOOTH)

            #
            # Begin draw
            #
            from math import sin, cos, pi, atan2, acos, sqrt
            from utilities import diff3D, dist3D

            def circle():
                for x in range(25):
                    theta = x * 2 * pi / 24
                    glVertex3f(cos(theta), sin(theta), 0.0)

            def halfcircle(start, end):
                for x in range(start, end):
                    theta = x * 2 * pi / 24
                    glVertex3f(cos(theta), sin(theta), 0.0)

            # Move into position to draw
            glLineWidth(1.0)
            glColor4f(1.0, 1.0, 1.0, 0.35)
            glPushMatrix()
            glTranslatef(89.0, 8.0, 0.001)
            glPushMatrix()

            glPushAttrib(GL_CURRENT_BIT)
            # Draw a circle to represent the XZ plane (bearing)
            glScalef(4.0, 4.0, 1.0)
            glBegin(GL_TRIANGLE_FAN)
            glVertex3f(0.0, 0.0, 0.0)
            circle()
            glEnd()

            # Draw the orientation of the camera
            glPushMatrix()
            glScalef(1.01, 1.01, 1.0)
            glColor4f(0.9, 0.9, 0.4, 0.9)
            glRotatef(180.0 * atan2(-1.0 * camera.vpn[Z_AXIS], camera.vpn[X_AXIS]) / pi, 0.0, 0.0, 1.0)
            glBegin(GL_TRIANGLE_FAN)
            glVertex3f(0.0, 0.0, 0.0)
            halfcircle(-2, 3)
            glEnd()
            glPopMatrix()

            # Draw the origin marker
            glPushMatrix()
            dOrigin = diff3D((0.0, 0.0, 0.0), camera.pos)

            glRotatef(270 - 180.0 * atan2(camera.pos[Z_AXIS], camera.pos[X_AXIS]) / pi - 90.0, 0.0, 0.0, 1.0)
            glColor4f(0.9, 0.2, 0.2, 0.95)
            glBegin(GL_TRIANGLES)
            glVertex3f(0.9, 0.0, 0.0)
            glVertex3f(1.1, -0.1, 0.0)
            glVertex3f(1.1, 0.1, 0.0)
            glEnd()
            glPopMatrix()

            # If there are vertices selected, draw vertex markers
            for v in vertices:
                glPushMatrix()
                dVertex = diff3D(v.pos, camera.pos)

                glRotatef(270 - 180.0 * atan2(dVertex[Z_AXIS], dVertex[X_AXIS]) / pi - 90.0, 0.0, 0.0, 1.0)
                glColor4f(0.2, 0.7, 0.9, 0.95)
                glBegin(GL_TRIANGLES)
                glVertex3f(0.9, 0.0, 0.0)
                glVertex3f(1.1, -0.1, 0.0)
                glVertex3f(1.1, 0.1, 0.0)
                glEnd()
                glPopMatrix()

            # Draw the X and Z axes on it
            glBegin(GL_LINE_STRIP)
            glColor3f(1.0, 0.5, 0.5)
            glVertex3f(-1.0, 0.0, 0.0)
            glVertex3f(-0.01, 0.0, 0.0)
            glColor3f(1.0, 0.0, 0.0)
            glVertex3f(0.0, 0.0, 0.0)
            glColor3f(0.5, 0.0, 0.0)
            glVertex3f(0.01, 0.0, 0.0)
            glVertex3f(1.0, 0.0, 0.0)
            glEnd()
            glBegin(GL_LINE_STRIP)
            glColor3f(0.5, 0.5, 1.0)
            glVertex3f(0.0, 1.0, 0.0)
            glVertex3f(0.0, 0.01, 0.0)
            glColor3f(0.0, 0.0, 1.0)
            glVertex3f(0.0, 0.0, 0.0)
            glColor3f(0.0, 0.0, 0.5)
            glVertex3f(0.0, -0.01, 0.0)
            glVertex3f(0.0, -1.0, 0.0)
            glEnd()
            glPopAttrib()
            # Done drawing XZ plane

            # Draw a half-circle to represent elevation
            glPushAttrib(GL_CURRENT_BIT)
            glTranslatef(2.2, 0.0, 0.0)
            glBegin(GL_TRIANGLE_FAN)
            halfcircle(6, 19)
            glEnd()

            # Draw the orientation of the camera
            glPushMatrix()
            glScalef(1.01, 1.01, 1.0)
            glColor4f(0.9, 0.9, 0.4, 0.9)
            glRotatef(90.0 + 180.0 * acos(utilities.dot_product(camera.vpn, (0.0, 1.0, 0.0))) / pi, 0.0, 0.0, 1.0)
            glBegin(GL_TRIANGLE_FAN)
            glVertex3f(0.0, 0.0, 0.0)
            halfcircle(-2, 3)
            glEnd()
            glPopMatrix()

            # Draw the zero-elevation line
            glBegin(GL_LINES)
            glColor4f(0.0, 0.0, 0.0, 1.0)
            glVertex3f(-1.0, 0.0, 0.0)
            glVertex3f(0.0, 0.0, 0.0)
            glEnd()

            # Draw the origin marker
            glPushMatrix()
            dOrigin = diff3D(camera.pos, (0.0, 0.0, 0.0))
            dist = dist3D(c=dOrigin)

            glRotatef(90.0 + 180.0 * acos(utilities.dot_product(dOrigin, (0.0, 1.0, 0.0)) / dist) / pi, 0.0, 0.0, 1.0)
            glColor4f(0.9, 0.2, 0.2, 0.95)
            glBegin(GL_TRIANGLES)
            glVertex3f(0.9, 0.0, 0.0)
            glVertex3f(1.1, -0.1, 0.0)
            glVertex3f(1.1, 0.1, 0.0)
            glEnd()
            glPopMatrix()

            # If there are vertices selected, draw vertex markers
            for v in vertices:
                glPushMatrix()
                dVertex = diff3D(v.pos, camera.pos)
                dist = dist3D(c=dVertex)

                glRotatef(270.0 - 180.0 * acos(utilities.dot_product(dVertex, (0.0, 1.0, 0.0)) / dist) / pi, 0.0, 0.0,
                          1.0)
                glColor4f(0.2, 0.7, 0.9, 0.95)
                glBegin(GL_TRIANGLES)
                glVertex3f(0.9, 0.0, 0.0)
                glVertex3f(1.1, -0.1, 0.0)
                glVertex3f(1.1, 0.1, 0.0)
                glEnd()
                glPopMatrix()

            # Clean up
            glPopMatrix()
            glPopAttrib()


            # Coordinates - if _pos_ is specified, draw that,
            # otherwise use the current position of the camera.
            if pos == None:
                pos = camera.pos

            glPushAttrib(GL_CURRENT_BIT)
            glPushMatrix()
            glTranslatef(-8.0, -7.0, 0.0)
            glScalef(0.009, 0.016, 1.0)
            # Draw the background box
            glBegin(GL_QUADS)
            glVertex3f(0.0, -40.0, 0.0)
            glVertex3f(2300.0, -40.0, 0.0)
            glVertex3f(2300.0, 140.0, 0.0)
            glVertex3f(0.0, 140.0, 0.0)
            glEnd()
            # Draw the text
            xS = ('%.1f' % pos[0]).rjust(6) + ' '
            yS = ('%.1f' % pos[1]).rjust(6) + ' '
            zS = ('%.1f' % pos[2]).rjust(6) + ' '
            glLineWidth(1.7)
            glColor4f(0.56, 0.0, 0.0, 0.9)
            for c in xS:
                glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, ord(c))
            glColor4f(0.0, 0.56, 0.0, 0.9)
            for c in yS:
                glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, ord(c))
            glColor4f(0.0, 0.0, 0.56, 0.9)
            for c in zS:
                glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, ord(c))
            glPopAttrib()
            glPopMatrix()

            glPopMatrix()

            #
            # end draw
            #


            #
            # now draw HUD status line
            #
            if status:
                glColor4f(1.0, 1.0, 1.0, 0.25)
                glPushMatrix()
                glTranslatef(0.0, 1.0, 0.001)
                glPushMatrix()

                glScalef(0.009, 0.016, 1.0)
                glBegin(GL_QUADS)
                glVertex3f(0.0, -40.0, 0.0)
                glVertex3f(5000.0, -40.0, 0.0)
                glVertex3f(5000.0, 140.0, 0.0)
                glVertex3f(0.0, 140.0, 0.0)
                glEnd()

                glLineWidth(1.4)
                glColor4f(0.56, 0.0, 0.0, 0.9)
                # Add some space before the first character
                glTranslatef(200.0, 0.0, 0.0)
                for c in status:
                    glutStrokeCharacter(GLUT_STROKE_ROMAN, ord(c))

                glPopMatrix()
                glPopMatrix()


            #
            # end HUD statusline draw
            #

            glPopMatrix()
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
            glEnable(GL_LIGHTING)
            glEnable(GL_DEPTH_TEST)
Example #12
0
def arrangeSpring(context, axes=(X_AXIS, Z_AXIS, Y_AXIS), sync=None, edgeTension=0.85, edgeLength=3.0,
                  useAttrEdgeK=False, invAttrEdgeK=False, useAttrEdgeLen=False, invAttrEdgeLen=False):
    """
    Arrange the vertices of the graph according to a force-directed
    spring model.
    """
    EPSILON = 0.1
    JITTER = EPSILON / 8
    TIMEINC = 0.7

    from utilities import jitterForce, repulseForce, springForce, diff3D, add3D
    from graph import DummyVertex

    balanced = False

    #
    # Set vertex mass
    #
    # XXX# Dummy vertices are 1/4 the mass of regular vertices.
    vxMass = dict([(v.id, (pi / 3.0, 2.0 * pi / 3.0)[isinstance(v, DummyVertex)]) for v in context.graph.vertices])

    #XXX# Scale by volume
    #vxMass = [4.0 * pi * v.radius * v.radius * v.radius / 3.0 for v in context.graph.vertices]

    #
    # Set vertex charge
    #
    vxCharge = dict([(v.id, 1.0) for v in context.graph.vertices])

    #
    # Set edge spring tensions
    #

    # The edgeTension parameter is specified in the range [0.0, 1.0].
    # Adjust it to be within reasonable bounds.
    if edgeTension > 1.0 or edgeTension < 0.0:
        raise GraphError, "Edge tension must be in the range [0.0, 1.0]"
    # 0.13 is practical (minimizing oscillations)
    # 0.11 is good (visibility separation)
    edgeTension = edgeTension * 0.15

    if useAttrEdgeK:
        edgeK = context.graph.normalizeFromEdges( \
            max=edgeTension, min=0.001, inv=invAttrEdgeK, \
            valFunc=lambda e: float(e.attribute), \
            failError="Some edge attributes could not be converted to float values for tension.")
    else:  # not useAttrEdgeK
        edgeK = dict([((e.source.id, e.target.id), edgeTension) for e in context.graph.edges])

    #
    # Set edge ideal length
    #
    # The edgeLength parameter must be >0.0

    if edgeLength <= 0.0:
        raise GraphError, "Edge length must be >0.0"
    if useAttrEdgeLen:
        edgeLen = context.graph.normalizeFromEdges( \
            max=edgeLength, min=0.0, inv=invAttrEdgeLen, \
            valFunc=lambda e: float(e.attribute), \
            failError="Some edge attributes could not be converted to float values for length.")
    else:
        edgeLen = dict([((e.source.id, e.target.id), edgeLength) for e in context.graph.edges])

    #
    # Set pass number
    #
    I = 0

    # Set changed flag now - if we set it after, then it's possible
    # that we could bail out without change flag getting set.
    context.graph.change()

    #
    # Do at least 2 passes to ensure that coincident vertices
    # get jittered apart.
    #
    while not balanced or I < 2:
        I = I + 1
        # Initialize the force on each vertex to 0.
        vxForceSum = dict([(x.id, (0.0, 0.0, 0.0)) for x in context.graph.vertices])
        balanced = True

        for v_num in range(len(context.graph.vertices)):
            v = context.graph.vertices[v_num]

            # Edges
            for u in v.nearestVertices():
                if u == v:
                    continue
                edges = context.graph.findEdgeBetween(u, v)
                for e in edges:
                    F = springForce(diff3D(v.pos, u.pos),
                                    Kuv=edgeK[(e.source.id, e.target.id)],
                                    Luv=edgeLen[(e.source.id, e.target.id)],
                                    j=JITTER)
                    vxForceSum[v.id] = add3D(vxForceSum[v.id], F)

            # Vertices
            for u in context.graph.vertices:
                if u == v:
                    continue
                F = repulseForce(diff3D(u.pos, v.pos),
                                 q1=vxCharge[u.id],
                                 q2=vxCharge[v.id],
                                 Cuv=300,
                                 j=JITTER)
                vxForceSum[v.id] = add3D(vxForceSum[v.id], F)

            # Jitter
            F = jitterForce(JITTER)
            vxForceSum[v.id] = add3D(vxForceSum[v.id], F)

            # Tether
            F = springForce(diff3D(v.pos, (0.0, 0.0, 0.0)), Kuv=0.005, Luv=1.0, j=JITTER)
            vxForceSum[v.id] = add3D(vxForceSum[v.id], F)

            if abs(vxForceSum[v.id][0]) > EPSILON and X_AXIS in axes or \
                                    abs(vxForceSum[v.id][1]) > EPSILON and Y_AXIS in axes or \
                                    abs(vxForceSum[v.id][2]) > EPSILON and Z_AXIS in axes:
                balanced = False

        # Now we have the force on each vertex.
        # Act on them.

        for v in context.graph.vertices:
            vel = ((X_AXIS in axes) * vxForceSum[v.id][0] * TIMEINC / vxMass[v.id],
                   (Y_AXIS in axes) * vxForceSum[v.id][1] * TIMEINC / vxMass[v.id],
                   (Z_AXIS in axes) * vxForceSum[v.id][2] * TIMEINC / vxMass[v.id])
            v.pos = add3D(v.pos, vel)

        if sync:
            # Because we're saving calls by referring to the vertices directly,
            # we have to set the change flag here, before we sync.
            context.graph.change()
            sync()
    context.graph.change()
    return I
Example #13
0
    def drawEdge(self, edge, alpha=1.0):
        """
        draw an edge in 3D.
        """

        # Superedge drawing is a no-op - all the parts will already have been
        # drawn.
        if isinstance(edge, SuperEdge):
            return

        if config.current['global:enable-anaglyph']:
            pigment = (1.0, 1.0, 1.0, alpha)
        else:
            pigment = edge.color + (alpha,)

        glColor4f(*pigment)

        # For Netcli (has no parent)
        ctx = self.graph.parent
        showG = False
        if not ctx == None:
            if ctx.showGrid:
                showG = True
        if showG:
            srcpos = utilities.mult3D(edge.source.pos, ctx.spacing)
            tgtpos = utilities.mult3D(edge.target.pos, ctx.spacing)
        else:
            srcpos = edge.source.pos
            tgtpos = edge.target.pos

        if config.current['global:draw-edge-cylinders']:
            diff = utilities.diff3D(srcpos, tgtpos)
            dist = utilities.dist3D(c=diff)

            # Avoid dividing by zero -
            # don't draw anything for zero-length edges
            if dist <= 0:
                return

            glPushMatrix()

            phi = acos(diff[Z_AXIS] / dist) * 180 / pi
            theta = atan2(diff[Y_AXIS], diff[X_AXIS]) * 180 / pi
            glTranslatef(*srcpos)
            glRotatef(theta, 0.0, 0.0, 1.0)
            glRotatef(phi, 0.0, 1.0, 0.0)
            gluQuadricOrientation(self.quad, GLU_OUTSIDE)
            gluQuadricTexture(self.quad, GL_TRUE)
            gluQuadricDrawStyle(self.quad, GLU_FILL)
            gluQuadricNormals(self.quad, GLU_SMOOTH)
            #glRotated(90, 1, 0, 0)
            gluCylinder(self.quad, edge.radius, edge.radius, dist, config.current['global:draw-edge-sides'],
                        config.current['global:draw-edge-sides'])
            glPopMatrix()

        else:  # not drawing edges as cylinders
            glDisable(GL_LIGHTING)
            glEnable(GL_LINE_SMOOTH)
            glLineWidth(config.current['global:draw-edge-linewidth'])
            glBegin(GL_LINES)
            glVertex3f(srcpos[0], srcpos[1], srcpos[2])
            glVertex3f(tgtpos[0], tgtpos[1], tgtpos[2])
            glEnd()
            glEnable(GL_LIGHTING)
Example #14
0
    def perspCameraMove(self, camera, newPos=None, newLook=None, duration=1.0, wait=0.0):
        """
        Moves the camera smoothly to a new position and orientation.
        If newLook is None, does not change the orientation of the camera.
        If newPos is None, does not change the position of the camera.
        """
        from camera import Camera, OrthoCamera, X_AXIS, Y_AXIS, Z_AXIS

        assert (not isinstance(camera, OrthoCamera))

        newCam = Camera()
        if newPos != None:
            newCam.pos = self.normalizePos(newPos)
        else:
            newCam.pos = camera.pos
        if newLook != None:
            newCam.lookAt = self.normalizePos(newLook)
        else:
            newCam.lookAt = camera.lookAt

        steps = int(duration * self.parent.fps)

        (oldTheta, oldPhi) = camera.polar()
        (newTheta, newPhi) = newCam.polar()

        deltaYaw = newTheta - oldTheta
        deltaPitch = newPhi - oldPhi
        deltaPos = diff3D(camera.pos, newCam.pos)

        # Check to make sure we're coming around the short side
        if deltaYaw > 180.0:
            deltaYaw = deltaYaw - 360.0
        elif deltaYaw < -180.0:
            deltaYaw = deltaYaw + 360.0
        print "DeltaYaw", deltaYaw

        stepYaw = deltaYaw / steps
        stepPitch = deltaPitch / steps
        stepPos = div3D(deltaPos, steps)

        accum = wait
        delay = 1.0 / self.parent.fps

        # Set up the animation
        for i in range(steps - 1):
            accum += delay

            self.post(accum,
                      objects=(
                      camera,
                      ),
                      props=(
                      (
                      'pos',
                      add3D(camera.pos, mult3D(stepPos, i + 1)),
                      ),
                      ),
                      call=(
                      ('absrotate', (Y_AXIS, stepYaw), {}),
                      ('rotate', (X_AXIS, stepPitch), {}),
                      ),
            )

        # Finish up in the correct place
        accum += delay
        self.post(accum,
                  objects=(camera,),
                  props=(
                  ('pos', newCam.pos),
                  ('lookAt', newCam.lookAt),
                  ),
        )

        self.signal()