<commit_before>package com.leakedbits.codelabs.box2d.controllers;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.leakedbits.codelabs.box2d.utils.PolygonProperties;
import com.leakedbits.codelabs.box2d.utils.PolygonUtils;

public class BuoyancyController {

	private Fixture fluidSensor;
	private List<Vector2> fluidVertices;
	private Set<Fixture> fixtures;
	private World world;

	public boolean isFluidFixed = true;
	public float fluidDrag = 0.25f;
	public float fluidLift = 0.25f;
	public float maxFluidDrag = 2000;
	public float maxFluidLift = 500;

	public BuoyancyController(World world, Fixture fluidSensor) {
		this.world = world;
		this.fluidSensor = fluidSensor;
		fluidVertices = getFixtureVertices(fluidSensor);

		fixtures = new HashSet<Fixture>();
	}

	public void step() {
		for (Fixture fixture : fixtures) {
			if (fixture.getBody().isAwake()) {

				/* Create clipPolygon */
				List<Vector2> clipPolygon = getFixtureVertices(fixture);

				/* Create subjectPolygon */
				List<Vector2> subjectPolygon;
				if (isFluidFixed) {
					subjectPolygon = fluidVertices;
				} else {
					subjectPolygon = getFixtureVertices(fluidSensor);
				}

				/* Get intersection polygon */
				List<Vector2> clippedPolygon = PolygonUtils.clipPolygons(
						subjectPolygon, clipPolygon);

				if (!clippedPolygon.isEmpty()) {
					applyForces(fixture, clippedPolygon.toArray(new Vector2[0]));
				}
			}
		}
	}

	private void applyForces(Fixture fixture, Vector2[] clippedPolygon) {
		PolygonProperties polygonProperties = PolygonUtils
				.computePolygonProperties(clippedPolygon);

		/* Get fixtures bodies */
		Body fixtureBody = fixture.getBody();
		Body fluidBody = fluidSensor.getBody();

		/* Get fluid density */
		float density = fluidSensor.getDensity();

		/* Apply buoyancy force */
		float displacedMass = fluidSensor.getDensity()
				* polygonProperties.getArea();
		Vector2 gravity = world.getGravity();
		Vector2 buoyancyForce = new Vector2(-gravity.x * displacedMass,
				-gravity.y * displacedMass);
		fixtureBody.applyForce(buoyancyForce, polygonProperties.getCentroid(),
				true);

		/* Apply drag and lift forces */
		int polygonVertices = clippedPolygon.length;
		for (int i = 0; i < polygonVertices; i++) {

			/* Apply drag force */

			/* End points and mid point of the edge */
			Vector2 firstPoint = clippedPolygon[i];
			Vector2 secondPoint = clippedPolygon[(i + 1) % polygonVertices];
			Vector2 midPoint = firstPoint.cpy().add(secondPoint).scl(0.5f);

			/*
			 * Find relative velocity between the object and the fluid at edge
			 * mid point.
			 */
			Vector2 velocityDirection = new Vector2(fixtureBody
					.getLinearVelocityFromWorldPoint(midPoint)
					.sub(fluidBody.getLinearVelocityFromWorldPoint(midPoint)));
			float velocity = velocityDirection.len();
			velocityDirection.nor();
            
			Vector2 edge = secondPoint.cpy().sub(firstPoint);
			float edgeLength = edge.len();
			edge.nor();
			
			Vector2 normal = new Vector2(edge.y, -edge.x);		
			float dragDot = normal.dot(velocityDirection); 
			
			if (dragDot >= 0) {
				
				/*<commit_msg>Add linear drag force to simulate fluid velocity<commit_after>package com.leakedbits.codelabs.box2d.controllers;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.leakedbits.codelabs.box2d.utils.PolygonProperties;
import com.leakedbits.codelabs.box2d.utils.PolygonUtils;

public class BuoyancyController {

	private Fixture fluidSensor;
	private List<Vector2> fluidVertices;
	private Set<Fixture> fixtures;
	private World world;

	public boolean isFluidFixed = true;
	public float fluidDrag = 0.25f;
	public float fluidLift = 0.25f;
	public float linearDrag = 0;
	public float maxFluidDrag = 2000;
	public float maxFluidLift = 500;

	public BuoyancyController(World world, Fixture fluidSensor) {
		this.world = world;
		this.fluidSensor = fluidSensor;
		fluidVertices = getFixtureVertices(fluidSensor);

		fixtures = new HashSet<Fixture>();
	}

	public void step() {
		for (Fixture fixture : fixtures) {
			if (fixture.getBody().isAwake()) {

				/* Create clipPolygon */
				List<Vector2> clipPolygon = getFixtureVertices(fixture);

				/* Create subjectPolygon */
				List<Vector2> subjectPolygon;
				if (isFluidFixed) {
					subjectPolygon = fluidVertices;
				} else {
					subjectPolygon = getFixtureVertices(fluidSensor);
				}

				/* Get intersection polygon */
				List<Vector2> clippedPolygon = PolygonUtils.clipPolygons(
						subjectPolygon, clipPolygon);

				if (!clippedPolygon.isEmpty()) {
					applyForces(fixture, clippedPolygon.toArray(new Vector2[0]));
				}
			}
		}
	}

	private void applyForces(Fixture fixture, Vector2[] clippedPolygon) {
		PolygonProperties polygonProperties = PolygonUtils
				.computePolygonProperties(clippedPolygon);

		/* Get fixtures bodies */
		Body fixtureBody = fixture.getBody();
		Body fluidBody = fluidSensor.getBody();

		/* Get fluid density */
		float density = fluidSensor.getDensity();

		/* Apply buoyancy force */
		float displacedMass = fluidSensor.getDensity()
				* polygonProperties.getArea();
		Vector2 gravity = world.getGravity();
		Vector2 buoyancyForce = new Vector2(-gravity.x * displacedMass,
				-gravity.y * displacedMass);
		fixtureBody.applyForce(buoyancyForce, polygonProperties.getCentroid(),
				true);

		/* Linear drag force */
		if (linearDrag != 0) {
			fixtureBody.applyForce(gravity.rotate90(1).nor().scl(linearDrag),
					polygonProperties.getCentroid(), true);
		}

		/* Apply drag and lift forces */
		int polygonVertices = clippedPolygon.length;
		for (int i = 0; i < polygonVertices; i++) {

			/* Apply drag force */

			/* End points and mid point of the edge */
			Vector2 firstPoint = clippedPolygon[i];
			Vector2 secondPoint = clippedPolygon[(i + 1) % polygonVertices];
			Vector2 midPoint = firstPoint.cpy().add(secondPoint).scl(0.5f);

			/*
			 * Find relative velocity between the object and the fluid at edge
			 * mid point.
			 */
			Vector2 velocityDirection = new Vector2(fixtureBody
					.getLinearVelocityFromWorldPoint(midPoint)
					.sub(fluidBody.getLinearVelocityFromWorldPoint(midPoint)));
			float velocity = velocityDirection.len();
			velocityDirection.nor();

			Vector2 edge = secondPoint.cpy().sub(firstPoint);
			float edgeLength = edge.len();
			edge.nor();

			Vector2 normal = new Vector2(edge.y, -edge.x);
			float dragDot = normal.dot(velocityDirection);

			if (dragDot >= 0) {

				/*
{'fraction_non_alphanumeric': 0.10928186204938972, 'fraction_numerical': 0.01319897814362759, 'mean_word_length': 4.037169406719085, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7252699', 'n_tokens_mistral': 2631, 'n_tokens_neox': 2223, 'n_words': 492}