/// <summary> /// Return PulsationBehaviour with appropriate frequency. /// Frequency is defined by the position of the HaptiQ within this HapticLink /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected override IBehaviour chooseBehaviour(HaptiQ haptiQ) { double highFrequency = _hasDirection ? 100 * (Helper.distanceBetweenTwoPoints(haptiQ.position, _pair.Item2) / Helper.distanceBetweenTwoPoints(_pair.Item2, _pair.Item1)) : DEFAULT_FREQUENCY; IBehaviour behaviour = new PulsationBehaviour(haptiQ, new Tuple<Point, Point>(_pair.Item1, _pair.Item2), highFrequency); return behaviour; }
/// <summary> /// Constructor for edge-corner behaviour. /// </summary> /// <param name="haptiQ"></param> /// <param name="lines">Geometric lines indicating the direction</param> public EdgeCornerBehaviour(HaptiQ haptiQ, List<Tuple<Point, Point>> lines) : base(haptiQ) { _lines = lines; TIME = 0; highPosition = HIGH_POSITION_PERCENTAGE; lowPosition = MIN_POSITION; }
/// <summary> /// Constructor of the Linear behaviour. /// Height of the actuators is specified by the ratio value /// </summary> /// <param name="haptiQ"></param> /// <param name="segment"></param> /// <param name="ratio"></param> public LinearBehaviour(HaptiQ haptiQ, Tuple<Point, Point> segment, double ratio) : base(haptiQ) { _segment = segment; TIME = 0; highPosition = HIGH_POSITION_PERCENTAGE * ratio; lowPosition = 0; }
/// <summary> /// Constructor of the pulsation behaviour. /// Make the specified actuators to pulse at a constant interval /// </summary> /// <param name="haptiQ"></param> /// <param name="segment"></param> /// <param name="frequency"></param> public PulsationBehaviour(HaptiQ haptiQ, Tuple<Point, Point> segment, double frequency) : base(haptiQ) { _segment = segment; _frequency = frequency; TIME = 0; highPosition = HIGH_POSITION_PERCENTAGE; lowPosition = 0; }
/// <summary> /// Behaviour constructor /// </summary> /// <param name="haptiQ"></param> public Behaviour(HaptiQ haptiQ) { this.actuators = haptiQ.getActuators(); this.position = haptiQ.position; this.orientation = haptiQ.orientation; actuatorsDict = new Dictionary<int, Actuator>(); foreach (Actuator actuator in actuators) { actuatorsDict[actuator.getId()] = actuator; } }
/// <summary> /// Output information content via audio if input was received /// for a device currently in this haptic rectangle /// </summary> /// <param name="haptiQ"></param> /// <param name="gestureType"></param> public override void handlePress(HaptiQ haptiQ, PRESSURE_GESTURE_TYPE gestureType) { Tuple<STATE, IBehaviour> HaptiQState = _HaptiQBehaviours.ContainsKey(haptiQ.getID()) ? _HaptiQBehaviours[haptiQ.getID()] : null; if (pointIsInside(haptiQ.position) && HaptiQState != null && HaptiQState.Item1 == STATE.down) { if (_action != null) { _action.run(haptiQ.getID(), gestureType, haptiQ.getCurrentPressureData()); } else { SpeechOutput.Instance.speak(information); } } }
/// <summary> /// Constructor for a NotificationBehaviour. /// </summary> /// <param name="haptiQ"></param> /// <param name="frequency"></param> public NotificationBehaviour(HaptiQ haptiQ, double frequency) : base(haptiQ) { TIME = 0; _frequency = frequency; _positions = new double[actuators.Count(), 2]; double position = 0.0; for (int i = 0; i < _positions.GetLength(0); i++) { position += 1.0 / (_positions.GetLength(0) - 1); _positions[i, 0] = position; _positions[i, 1] = 1; } }
/// <summary> /// Constructor for a BasicBehaviour. /// </summary> /// <param name="haptiQ"></param> /// <param name="type"></param> /// <param name="frequency"></param> public BasicBehaviour(HaptiQ haptiQ, TYPES type, double frequency) : base(haptiQ) { _type = type; TIME = 0; _frequency = frequency; highPosition = DEFAULT_POS; lowPosition = MIN_POSITION; if (type == TYPES.flat) { _actuatorsToActivate = 0; } else if (type == TYPES.max) { _actuatorsToActivate = (int) (Math.Pow(2, actuators.Count()) - 1); } else { _actuatorsToActivate = 0; Helper.Logger("HaptiQ_API.BasicBehaviour.BasicBehaviour::type " + type + " undefined"); } }
/// <summary> /// Constructor for a BasicBehaviour. /// </summary> /// <param name="haptiQ"></param> /// <param name="type"></param> public BasicBehaviour(HaptiQ haptiQ, TYPES type) : this(haptiQ, type, DEFAULT_FREQUENCY) { }
/// <summary> /// Return a notificationBehaviour with frequency dictated by the /// position of the HaptiQ within this shape /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected override IBehaviour chooseBehaviour(HaptiQ haptiQ) { return new NotificationBehaviour(haptiQ, getFrequency(haptiQ.position)); }
/// <summary> /// Return an Edge-Corner behaviour based on the position of the haptiQ /// on this polyline /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected override IBehaviour chooseBehaviour(HaptiQ haptiQ) { return new EdgeCornerBehaviour(haptiQ, _lines); }
/// <summary> /// Handle behaviours on input /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> public Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour> handleInput(HaptiQ haptiQ) { if (this.Parent != null) { Tuple<STATE, IBehaviour> HaptiQState = _HaptiQBehaviours.ContainsKey(haptiQ.getID()) ? _HaptiQBehaviours[haptiQ.getID()] : null; if (pointIsInside(haptiQ.position)) { IBehaviour prevBehaviour = HaptiQState != null ? HaptiQState.Item2 : null; IBehaviour currentBehaviour = chooseBehaviour(haptiQ); currentBehaviour.updateNext(prevBehaviour); BEHAVIOUR_RULES rule = BEHAVIOUR_RULES.SUBS; if (currentBehaviour.Equals(prevBehaviour)) { rule = BEHAVIOUR_RULES.NOPE; } _HaptiQBehaviours[haptiQ.getID()] = new Tuple<STATE, IBehaviour>(STATE.down, currentBehaviour); return new Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour>(rule, currentBehaviour, prevBehaviour); } else if (HaptiQState != null && HaptiQState.Item1 == STATE.down) { IBehaviour prevBehaviour = HaptiQState.Item2; IBehaviour currentBehaviour = new BasicBehaviour(haptiQ, BasicBehaviour.TYPES.flat); BEHAVIOUR_RULES rule = BEHAVIOUR_RULES.SUBS; if (currentBehaviour.Equals(prevBehaviour)) { rule = BEHAVIOUR_RULES.NOPE; } _HaptiQBehaviours[haptiQ.getID()] = new Tuple<STATE, IBehaviour>(STATE.up, currentBehaviour); return new Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour>(rule, currentBehaviour, prevBehaviour); } } Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour> retval = new Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour>(BEHAVIOUR_RULES.REMOVE, _HaptiQBehaviours.ContainsKey(haptiQ.getID()) ? _HaptiQBehaviours[haptiQ.getID()].Item2 : null, null); _HaptiQBehaviours[haptiQ.getID()] = new Tuple<STATE, IBehaviour>(STATE.up, null); return retval; }
/// <summary> /// Return appropriate behaviour based on the position of the HaptiQ within /// this HapticRectangle /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected override IBehaviour chooseBehaviour(HaptiQ haptiQ) { IBehaviour behaviour = null; Point bottomLeft = new Point(x, y + height); Point bottomRight = new Point(x + width, y + height); Point topLeft = new Point(x, y); Point topRight = new Point(x + width, y); List<Tuple<Point, Point>> lines = new List<Tuple<Point, Point>>(); if (pointIsCloseToSegment(haptiQ.position, bottomLeft, bottomRight, CORNER_NEARNESS_TOLLERANCE) && pointIsCloseToSegment(haptiQ.position, bottomLeft, topLeft, CORNER_NEARNESS_TOLLERANCE)) // bottom-left corner { lines.Add(new Tuple<Point, Point>(bottomLeft, bottomRight)); lines.Add(new Tuple<Point, Point>(bottomLeft, topLeft)); } else if (pointIsCloseToSegment(haptiQ.position, topLeft, topRight, CORNER_NEARNESS_TOLLERANCE) && pointIsCloseToSegment(haptiQ.position, topLeft, bottomLeft, CORNER_NEARNESS_TOLLERANCE)) // top-left corner { lines.Add(new Tuple<Point, Point>(topLeft, topRight)); lines.Add(new Tuple<Point, Point>(topLeft, bottomLeft)); } else if (pointIsCloseToSegment(haptiQ.position, topRight, topLeft, CORNER_NEARNESS_TOLLERANCE) && pointIsCloseToSegment(haptiQ.position, topRight, bottomRight, CORNER_NEARNESS_TOLLERANCE)) // top-right corner { lines.Add(new Tuple<Point, Point>(topRight, topLeft)); lines.Add(new Tuple<Point, Point>(topRight, bottomRight)); } else if (pointIsCloseToSegment(haptiQ.position, bottomRight, topRight, CORNER_NEARNESS_TOLLERANCE) && pointIsCloseToSegment(haptiQ.position, bottomRight, bottomLeft, CORNER_NEARNESS_TOLLERANCE)) // bottom-right corner { lines.Add(new Tuple<Point, Point>(bottomRight, topRight)); lines.Add(new Tuple<Point, Point>(bottomRight, bottomLeft)); } else if (pointIsCloseToSegment(haptiQ.position, bottomLeft, bottomRight, NEARNESS_TOLLERANCE)) // horizontal { lines.Add(new Tuple<Point, Point>(bottomLeft, bottomRight)); } else if (pointIsCloseToSegment(haptiQ.position, topLeft, topRight, NEARNESS_TOLLERANCE)) // horizontal { lines.Add(new Tuple<Point, Point>(topLeft, topRight)); } else if (pointIsCloseToSegment(haptiQ.position, topLeft, bottomLeft, NEARNESS_TOLLERANCE)) // vertical { lines.Add(new Tuple<Point, Point>(topLeft, bottomLeft)); } else if (pointIsCloseToSegment(haptiQ.position, topRight, bottomRight, NEARNESS_TOLLERANCE)) // vertical { lines.Add(new Tuple<Point, Point>(topRight, bottomRight)); } else { behaviour = new BasicBehaviour(haptiQ, BasicBehaviour.TYPES.max); } if (behaviour == null) { behaviour = new EdgeCornerBehaviour(haptiQ, lines); } return behaviour; }
/// <summary> /// Return a behaviour for this haptic shape /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected abstract IBehaviour chooseBehaviour(HaptiQ haptiQ);
/// <summary> /// Registers an HaptiQ. /// Returns not updated id if HaptiQ could not be added. /// </summary> /// <param name="haptiQ"></param> /// <returns> unique id assigned to HaptiQ </returns> public UInt32 addHaptiQ(HaptiQ haptiQ) { if (haptiQ == null) { Helper.Logger("HaptiQ_API.HaptiQsManager.addHaptiQ:: HaptiQ is null"); return _nextID; } else { haptiQ.PositionChanged += new PositionEventHandler(HaptiQ_PositionChanged); haptiQ.PressureInput += new PressureInputEventHandler(HaptiQ_PressureInput); haptiQ.ActuatorPositionChanged += new ActuatorPositionEventHandler(HaptiQ_ActuatorPositionChanged); haptiQ.PressureGesture += new PressureGestureEventHandler(pressureGestureHaptiQChanged); _HaptiQsDictionary.Add(_nextID, haptiQ); _inputIdentifiersToHaptiQs.Add(haptiQ.configuration.inputIdentifier, _nextID); return _nextID++; } }
private void handleBehaviours(HaptiQ haptiQ, Point point, double orientation) { // Notify observers lock (_syncObj) { Parallel.ForEach(_hapticObjectObservers, observer => { Tuple<BEHAVIOUR_RULES, IBehaviour, IBehaviour> behaviour = observer.handleInput(haptiQ); switch (behaviour.Item1) { case BEHAVIOUR_RULES.ADD: haptiQ.addBehaviour(behaviour.Item2); break; case BEHAVIOUR_RULES.REMOVE: haptiQ.removeBehaviour(behaviour.Item2); break; case BEHAVIOUR_RULES.SUBS: // Substitute behaviours haptiQ.removeBehaviour(behaviour.Item3); haptiQ.addBehaviour(behaviour.Item2); break; case BEHAVIOUR_RULES.NOPE: // Do nothing break; default: Helper.Logger("HaptiQ_API.HaptiQsManager.handleBehaviours:: observed returned unknown rule for behaviour"); break; } }); } }
private void createHaptiQs(List<Configuration> configurations) { if (configurations != null && configurations.Count > 0) { foreach (Configuration configuration in configurations) { HaptiQ haptiQ = new HaptiQ(_nextID, configuration); addHaptiQ(haptiQ); // Add this HaptiQ to HaptiQsManager appropriate data structure } } }
/// <summary> /// Constructor for a NotificationBehaviour. /// </summary> /// <param name="haptiQ"></param> public NotificationBehaviour(HaptiQ haptiQ) : this(haptiQ, DEFAULT_FREQUENCY) { }
/// <summary> /// Returns an edge-corner behaviour based on the position of the HaptiQ /// on the HapticLine /// </summary> /// <param name="haptiQ"></param> /// <returns></returns> protected override IBehaviour chooseBehaviour(HaptiQ haptiQ) { List<Tuple<Point, Point>> lines = new List<Tuple<Point, Point>>(); lines.Add(_pair); return new EdgeCornerBehaviour(haptiQ, lines); }
/// <summary> /// Handle an actuator press. /// Note: Multiple presses are not supported, yet. /// </summary> /// <param name="haptiQ"></param> /// <param name="gestureType"></param> public virtual void handlePress(HaptiQ haptiQ, PRESSURE_GESTURE_TYPE gestureType) { Tuple<STATE, IBehaviour> HaptiQState = _HaptiQBehaviours.ContainsKey(haptiQ.getID()) ? _HaptiQBehaviours[haptiQ.getID()] : null; if (pointIsInside(haptiQ.position) && HaptiQState != null && HaptiQState.Item1 == STATE.down) { if (_action != null) { _action.run(haptiQ.getID(), gestureType, haptiQ.getCurrentPressureData()); } } }