Path: blob/master/scene/resources/2d/convex_polygon_shape_2d.cpp
9903 views
/**************************************************************************/1/* convex_polygon_shape_2d.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "convex_polygon_shape_2d.h"3132#include "core/math/geometry_2d.h"33#include "servers/physics_server_2d.h"34#include "servers/rendering_server.h"3536bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {37return Geometry2D::is_point_in_polygon(p_point, points);38}3940#ifdef DEBUG_ENABLED41// Check if point p3 is to the left of [p1, p2] segment or on it.42bool left_test(const Vector2 &p1, const Vector2 &p2, const Vector2 &p3) {43Vector2 p12 = p2 - p1;44Vector2 p13 = p3 - p1;45// If the value of the cross product is positive or zero; p3 is to the left or on the segment, respectively.46return p12.cross(p13) >= 0;47}4849bool is_convex(const Vector<Vector2> &p_points) {50// Pre-condition: Polygon is in counter-clockwise order.51int polygon_size = p_points.size();52for (int i = 0; i < polygon_size && polygon_size > 3; i++) {53int j = (i + 1) % polygon_size;54int k = (j + 1) % polygon_size;55// If any consecutive three points fail left-test, then there is a concavity.56if (!left_test(p_points[i], p_points[j], p_points[k])) {57return false;58}59}6061return true;62}63#endif6465void ConvexPolygonShape2D::_update_shape() {66Vector<Vector2> final_points = points;67if (Geometry2D::is_polygon_clockwise(final_points)) { //needs to be counter clockwise68final_points.reverse();69}70#ifdef DEBUG_ENABLED71if (!is_convex(final_points)) {72WARN_PRINT("Concave polygon is assigned to ConvexPolygonShape2D.");73}74#endif75PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), final_points);76emit_changed();77}7879void ConvexPolygonShape2D::set_point_cloud(const Vector<Vector2> &p_points) {80Vector<Point2> hull = Geometry2D::convex_hull(p_points);81ERR_FAIL_COND(hull.size() < 3);82set_points(hull);83}8485void ConvexPolygonShape2D::set_points(const Vector<Vector2> &p_points) {86points = p_points;8788_update_shape();89}9091Vector<Vector2> ConvexPolygonShape2D::get_points() const {92return points;93}9495void ConvexPolygonShape2D::_bind_methods() {96ClassDB::bind_method(D_METHOD("set_point_cloud", "point_cloud"), &ConvexPolygonShape2D::set_point_cloud);97ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape2D::set_points);98ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape2D::get_points);99100ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "points"), "set_points", "get_points");101}102103void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {104if (points.size() < 3) {105return;106}107108Vector<Color> col = { p_color };109RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col);110111if (is_collision_outline_enabled()) {112col = { Color(p_color, 1.0) };113RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);114// Draw the last segment.115RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], Color(p_color, 1.0));116}117}118119Rect2 ConvexPolygonShape2D::get_rect() const {120Rect2 rect;121for (int i = 0; i < points.size(); i++) {122if (i == 0) {123rect.position = points[i];124} else {125rect.expand_to(points[i]);126}127}128129return rect;130}131132real_t ConvexPolygonShape2D::get_enclosing_radius() const {133real_t r = 0.0;134for (int i(0); i < get_points().size(); i++) {135r = MAX(get_points()[i].length_squared(), r);136}137return Math::sqrt(r);138}139140ConvexPolygonShape2D::ConvexPolygonShape2D() :141Shape2D(PhysicsServer2D::get_singleton()->convex_polygon_shape_create()) {142}143144145